Reputation: 56
I have long test that call a lot of functions that test the all application. I looking for a way that in case of failure in the test, I can rollback the specific changes that the automation did on the test.
For example:
test "add user and login", session do
session
|> add_user()
# There can be more functions here...
end
def add_user(session, loops // 2) do
try do
session
|> visit("example.com")
|> fill_in(css("#user_name", with "John Doe")
|> click(css("#add_user_button"))
|> assert_has(css("#user_added_successfully_message")
rescue
msg -> if loops > 0, do: add_user(session, loops - 1), else: raise msg
end
end
In case of failure on the assert_has function (the user aded but the message don't show up), I want to rollback all the changes that happened on the database before the add_user function called again in the rescue.
Upvotes: 0
Views: 221
Reputation: 3437
In case you use Ecto
to access the DB everywhere, you can use its sandbox mode.
Most likely you want to configure the sandbox pool in your config/test.exs
(if not already there):
config :my_app, Repo, # my_app being the name of the application that holds the Repo
pool: Ecto.Adapters.SQL.Sandbox
Then in your test_helper or tests do something like this:
setup do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(Repo)
Ecto.Adapters.SQL.Sandbox.mode(Repo, {:shared, self()})
end
With this, all your tests run in separate transactions and are rolled back afterwards. Also the above makes sure that all the processes use the same connection and see the same transaction data (see :shared
mode in the docs).
This example is taken from the the docs where there is more information on that.
If you can not use Ectos sandbox mode for whatever reason, a good option could be to start a database transaction yourself and share the connection between your test and the code under test. That way you can manually roll back after each test.
Upvotes: 0