Snapshot, a library for making tests fast

I just took the time to open source snapshot. It’s a simple library that makes testing modules that are slow because of side effects and make them run as fast and reliable as the other tests by creating snapshots of function calls and outputs. It just involves adding a single line to your module.

This makes it easy testing complex behaviour of modules that involve network or computational intensive work, snapshotting the bottlenecks, and have the test run every-time instead of putting them behind a separate tag because they are slow.

Note: if the inputs change every requests this will not work. In that case you should set up a mock module with some business logic.

Really interested to know what you think, and how it might be improved.

3 Likes

Hi!

Could it be possible to use Snapshot only in tests?

For example, in test/support/client.ex I would define an extension to lib/client.ex only for tests like

defmodule Test.Client do
  use Snapshot, for: Client
end

and lib/*.ex would be free of testing logic?

On second thought, it’s probably not possible, since then Snapshot won’t have access to the AST of the module it tries to rewrite.

1 Like

Yes that would definitely be better, but it’s not possible to my knowledge!

Maybe you could retrieve the AST from the module you want to test and real compile it with whatever custom transformations you need.

This is probabky something you shoud never ever do in production. Elixir makes it intentionally hard (almost impossible?) for a macro in one module to cause changes in another module, but for testing ir might be ok

1 Like

@OvermindDL1, I know this is definitely not the elixir way (probably the elixir forbidden road or something), but how can one have access to a module’s AST? Having access to the .beam file is easy, but there might be better ways to apply source transformations to a module. Instrumenting the .beam bytecode seems suboptimal.

Well if you don’t mind injecting code into it then just decorating the defmodule or so would do it.

Otherwise just read in the source file and run it through the string_to_quoted or whatever it was called function. :slight_smile:

If you are injecting anyway then you could just do this instead:

require Snapshot
Snapshot.decorate_test defmodule Test.Client do
  ...
end

Or whatever you want to call it. :slight_smile: