module Divider::Testing

Helpers for an application's tests: run jobs as they are enqueued (inline), record enqueues without inserting (fake), or run what the table holds (drain).

class Ping < Divider::Job
  def perform(job: Divider::Context) -> Void
    job.repo.exec("INSERT INTO pings DEFAULT VALUES")
  end
end

class PingTest < Test::Case
  include Divider::Testing::Assertions

  def repo -> Rotor::Repo = Rotor::Repo.new(pool: PG::Pool.new(ENV["DATABASE_URL"]))

  def test_enqueued
    Divider::Testing.fake do
      Ping.enqueue(repo)
      assert_enqueued(Ping)
    end
  end

  def test_run
    Divider::Testing.inline(repo) { Ping.enqueue(repo) }
    assert_equal(1, repo.query("SELECT count(*) FROM pings") { |r| r.int(0) }[0])
  end
end

Under fake, unique is not applied (each enqueue is recorded). Under inline, a job enqueued at: or after: a time runs at once too, and a unique enqueue that gives back a live job runs nothing.

inline and fake set a mode for the whole process (Quarz has no storage per task): they are not for tests run in parallel (quarz test --parallel).

/home/runner/work/divider/divider/src/testing.qz:38

Classes and modules

Class methods

def self.fake[R](&: () -> R) -> R

Runs the block with enqueues recorded instead of inserted (each given an Enqueued with an id from -1 down, available, or scheduled at at); the records stay readable (enqueued) until the next fake.

/home/runner/work/divider/divider/src/testing.qz:54

def self.enqueued(job: Type[Divider::Job]? = …) -> Array[Divider::Testing::Recorded]

What fake recorded, of the class job (every class without it), in order.

/home/runner/work/divider/divider/src/testing.qz:65

def self.inline[R](repo: Rotor::Repo, &: () -> R) -> R

Runs the block with each job enqueued run at once, in the calling task, over repo: one enqueued outside a transaction when it is enqueued, one enqueued inside a transaction at the next enqueue outside one, or when the block ends (a rolled-back one has no row, and does not run). Jobs run as a worker runs them (their outcome recorded in the row): a Snooze leaves the job scheduled, not run again.

/home/runner/work/divider/divider/src/testing.qz:76

def self.drain(repo: Rotor::Repo, *, jobs: Array[Type[Divider::Job]]) -> Int

Runs, once, in the calling task, the jobs of the classes jobs due now in the table (not those they enqueue): how many ran.

/home/runner/work/divider/divider/src/testing.qz:93