hyperfiddle / hyperfiddle/rcf

Change the rcf timeout for async tests inside of tests?

Open
#33 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Clojure
Stars
301
Forks
14
PR merge metrics
No merged PRs in 30d

Description

I have some tests where I want to assert timing, for example:

(rcf/set-timeout! 1)
(tests
    "Awaits all promise-chan in given vector and returns a vector of their results in order. Promise-chans obviously run concurrently, so the entire operation will take as long as the longest one."
    (rcf/set-timeout! 210)
    (async
     (! (await (all [1 (timeout 100 2) (timeout 200 3)]))))
    % := [1 2 3])

Now this test will fail, because it seems the call to (rcf/set-timeout! 210) won't change the timeout of the test. This is kind of annoying, because when I have many tests which I need to control timeouts differently I have to do:

(do
  (rcf/set-timeout! 210)
  (tests
    "Awaits all promise-chan in given vector and returns a vector of their results in order. Promise-chan obviously run concurrently, so the entire operation will take as long as the longest one."
    (async
     (! (await (all [1 (timeout 100 2) (timeout 200 3)]))))
    % := [1 2 3])

  (rcf/set-timeout! 20)
  (tests
    "Short-circuits as soon as one promise-chan errors, returning the error."
    (async
     (try
       (await (all [(timeout 10 #(/ 1 0)) (timeout 100 2) (timeout 200 3)]))
       (catch Exception e
         (! e))))
    (type %) := ArithmeticException)

  (rcf/set-timeout! 1000)
  (tests
    "Can contain non-promise-chan as well."
    (async
     (! (await (all [1 2 3]))))
    % := [1 2 3]

    "But since all is not a macro, if one of them throw it throws"
    (try (all [1 (timeout 10 2) (/ 1 0)])
         (catch Exception e
           (! e)))

    (type %) := ArithmeticException))

What I'd like to do instead is:

(tests
    "Awaits all promise-chan in given vector and returns a vector of their results in order. Promise-chan obviously run concurrently, so the entire operation will take as long as the longest one."
  (rcf/set-timeout! 210)
  (async
   (! (await (all [1 (timeout 100 2) (timeout 200 3)]))))
  % := [1 2 3])

  "Short-circuits as soon as one promise-chan errors, returning the error."
  (rcf/set-timeout! 20)
    (async
     (try
       (await (all [(timeout 10 #(/ 1 0)) (timeout 100 2) (timeout 200 3)]))
       (catch Exception e
         (! e))))
    (type %) := ArithmeticException)

  (rcf/set-timeout! 1000)
  "Can contain non-promise-chan as well."
  (async
    (! (await (all [1 2 3]))))
  % := [1 2 3]

  "But since all is not a macro, if one of them throw it throws"
  (try (all [1 (timeout 10 2) (/ 1 0)])
       (catch Exception e
         (! e)))

  (type %) := ArithmeticException))

I'd be happy if I could use (binding [rcf/*timeout*]) or something similar as well to wrap my individual tests inside the tests block too.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing rcf/set-timeout! and the tests macro, then inspect how timeout state is applied while async tests run. Done means individual tests inside a tests block can set or bind their own timeout, and the timing examples pass without wrapping each test in a separate do block.

Written by the indexing model from the issue text.

Assessment

Tech stack
clojure
Domain
testing
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.