Please do give a pull request a try then!

*José Valimhttps://dashbit.co/ <https://dashbit.co/>*


On Tue, Jun 16, 2026 at 4:06 PM Christopher Keele <[email protected]>
wrote:

> > What we typically do is that we never delete it by default, instead we
> clean up when the next test runs. The rationale is:
> >
> > 1. Leave resources for debugging
> > 2. If tests are interrupted (ctrl+c or whatever other reason), you need
> to deal with trailing resources anyway
> >
> > Would that be a problem here?
>
> What I'm toying with is a fork of *Ecto.Adapters.SQL.Sandbox* that
> implements test isolation by doing a full clean copy of the test database
> during setup per test, each copy named after the test in question, and
> redirecting all test interaction to the copy, rather than using
> transactions to get isolation. The goal is to support concurrent tests for
> Sqlite and to allow introspecting database state on test failure for Sqlite
> and Postgres. So in this case,
>
> 1. Tearing down the resource unconditionally *on_exit* is not desired (to
> have a debuggable state left)
> 2. Leaving behind every resource on successful tests is not desirable
> (that's a lot of wasted disk space after running 2000 stateful tests)
> 3. Keeping resources for failed tests and juggling *N* extra copies on
> disk where test parallelism is *N* is just about manageable
>
> Under this mechanism, leaving test failure resources behind is manageable,
> as is leaving *N* copies behind on test interruption, and all leftover
> state is overwritable on next test run, but leaving *all copies* behind
> is not viable for non-trivial test suites sizes or large seed databases.
> The worst case then becomes some errant global configuration causing every
> stateful test to fail—the mostly likely way that would happen is by
> providing a bad database configuration itself, which would prevent creation
> in the first place, preventing disk bloat from happening to begin with.
> On Tuesday, June 16, 2026 at 3:19:03 AM UTC-5 José Valim wrote:
>
>> > However, I would also like to leave the resource in-place on test
>> failure for inspection. (My *prepare_resource* function can handle the
>> situation where a resource already exists on setup. This is opposite to the
>> common tmpdir pattern where the resource cleans itself up automatically
>> upon test conclusion but would have unexpected side effects if already
>> setup.)
>>
>> What we typically do is that we never delete it by default, instead we
>> clean up when the next test runs. The rationale is:
>>
>> 1. Leave resources for debugging
>> 2. If tests are interrupted (ctrl+c or whatever other reason), you need
>> to deal with trailing resources anyway
>>
>> Would that be a problem here?
>>
>> *José Valimhttps://dashbit.co/ <https://dashbit.co/>*
>>
>>
>> On Tue, Jun 16, 2026 at 1:31 AM Christopher Keele <[email protected]>
>> wrote:
>>
>>> Assuming, of course I wrote this proposal without the typo in the final
>>> sentence and properly used an anonymous function for *on_exit(fn state
>>> -> #... end)* in my examples.
>>>
>>> On Monday, June 15, 2026 at 6:27:48 PM UTC-5 Christopher Keele wrote:
>>>
>>>> I am creating a resource during test setup based on a test's context
>>>> (namely, its module and name):
>>>>
>>>>
>>>>
>>>> *setup context do  prepare_resource_for_test_context(context)end*
>>>>
>>>> I would like to be able to teardown this resource upon test conclusion.
>>>> This is possible today:
>>>>
>>>>
>>>> *setup context do  prepare_resource_for_test_context(context)*
>>>> *  on_exit do*
>>>> *    cleanup_resource_for_test_context(context)*
>>>> *  end*
>>>> *end*
>>>>
>>>> *Proposal*
>>>>
>>>> However, I would also like to leave the resource in-place on test
>>>> failure for inspection. (My *prepare_resource* function can handle the
>>>> situation where a resource already exists on setup. This is opposite to the
>>>> common tmpdir pattern where the resource cleans itself up automatically
>>>> upon test conclusion but would have unexpected side effects if already
>>>> setup.)
>>>>
>>>> As far as I know, this is not possible today. I would like to do
>>>> something like receiving the *ExUnit.state()*
>>>> <https://ex-unit.hexdocs.pm/ExUnit.html#t:state/0> in the *on_exit*
>>>> callback:
>>>>
>>>>
>>>> *setup context do  prepare_resource_for_test_context(context)*
>>>> *  on_exit state do*
>>>>     *case state do*
>>>> *      {:failed, _} -> :ok*
>>>> *      _ -> cleanup_resource_for_test_context(context)*
>>>> *    end*
>>>> *  end*
>>>> *end*
>>>>
>>>> Are there reasons to not entertain this functionality? Is there another
>>>> way to accomplish it that doesn't rely on a test formatter to notice 
>>>> *{:test_finished,
>>>> test}* and do the cleanup at a global level?
>>>>
>>>> *Implementation*
>>>>
>>>> AFAICT we could enable this usecase trivially by threading
>>>> *test_or_case.state* into
>>>> <https://github.com/elixir-lang/elixir/blob/1d599978f7d36ea6896b294b3d26d110212be7ab/lib/ex_unit/lib/ex_unit/runner.ex#L541>*ExUnit.OnExitHandler.run
>>>> <https://github.com/elixir-lang/elixir/blob/1d599978f7d36ea6896b294b3d26d110212be7ab/lib/ex_unit/lib/ex_unit/runner.ex#L541>
>>>>  *and
>>>> on to its helper functions.
>>>>
>>>> We could retain backwards-compatibility by having *exec_callback(callback,
>>>> state)*
>>>> <https://github.com/elixir-lang/elixir/blob/1d599978f7d36ea6896b294b3d26d110212be7ab/lib/ex_unit/lib/ex_unit/on_exit_handler.ex#L139>
>>>> check the arity of the callback before invoking it.
>>>>
>>>> Documentation could describe the optional callback parameter and
>>>> elaborate that an *on_exit* callback defined in a *setup_all* would
>>>> have some other behaviour (raise an error, receive *nil* or the case
>>>> name instead of a state, etc—open to ideas).
>>>>
>>>> Are would such an implementation be welcome?
>>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "elixir-lang-core" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to [email protected].
>>> To view this discussion visit
>>> https://groups.google.com/d/msgid/elixir-lang-core/71b223e9-3815-4b8d-9ac0-cb32b98b05e8n%40googlegroups.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/71b223e9-3815-4b8d-9ac0-cb32b98b05e8n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion visit
> https://groups.google.com/d/msgid/elixir-lang-core/b4f28831-a68d-4d27-8239-7042cc64c469n%40googlegroups.com
> <https://groups.google.com/d/msgid/elixir-lang-core/b4f28831-a68d-4d27-8239-7042cc64c469n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4KghLgkz11O%3DrU5Z0gE%3DJx8NAuMW7sRpbEwQeLt5f26RQ%40mail.gmail.com.

Reply via email to