Let’s say I’m writing a (rather typical) application using Ecto, which heavily relies on a database.
Most features, let’s say, read from or write to the database. Let’s say I have feature “foo” which reads from multiple tables, does some non-trivial transformations and splits out the result. Let’s also say this feature has a simple interface in form of a single public function foo/1
.
How to approach property-testing this function?
My approach, so far, is as follows (I’m using PropCheck):
- Write some generators
- Setup test framework (ExUnit + Ecto.Adapters.SQL.Sandbox)
- Spin
forall
in a single test - Seed generated data into the database
- Perform the test
- Repeat last three steps X number of times
In code:
property "bla bla bla" do
forall dataset <- Gen.foo_dataset() do
Repo.transaction(fn ->
seed(dataset)
# perfom the test
assert ... = foo(...)
Repo.rollback(:test_end)
end)
end
end
(I’m skipping some non-essential bits)
The problems are:
- a lot of data is generated, so tests are very expensive due to all the database inserts
- Ecto sandbox is useless here because I’m inside a property (which basically is a loop) and transaction must be used to rollback data at the end of the test
I’m relatively new to Elixir, so I’m wondering, is this acceptable approach? Can this be done better conceptually?
Thanks!