Features, described gradually
Last updated
Was this helpful?
Last updated
Was this helpful?
There's a form-handling workflow that I'm going to call "Ecto Classic":
Form data (strings) is given to code that converts it into Elixir values (like integers or dates) and also validates the results.
If the resulting is marked invalid, the user is given another chance to fill in the form.
Otherwise, the changeset encapsulates values to be inserted into a database or used to update an existing row.
However, the database might complain about violated constraints like an attempt to or violate .
If a constraint is violated, the user is given another chance to fix the problem.
Otherwise, the task is done (though the results of the database update might be displayed to the user).
I'll start with an absurdly simple Ecto :
An example module holds a series of examples, each of which is (for the moment) just a way of writing input parameters. The module starts like this:
The create_test_data
function is called (using reflection) to create a big test data structure. The starting step (line 6) is to note the module under test (so that its functions, like Basic.changeset
, can be called). It also describes the :format
of the parameters, which will come into play shortly.
Let's create examples that represent both successful validation and validation failure. (We'll leave aside constraint-checking and use of the database for now.) That looks like this:
For now, you can consider the categories
purely for documentation, but they'll have a bigger role to play later.
The four examples each describe parameters to be checked by Basic.changeset
. Notice that the parameters are described as Elixir values, rather than the strings you'd get from HTTP. That rarely matters, in that Elixir's cast
is perfectly happy casting either the string "1"
or the integer 1
to a Schema's :integer
field, and it doesn't care whether that value belongs to the key "age"
or the key :age
.
However, I'm a stickler for realism, so the global format: :phoenix
option converts the parameters into the same format Phoenix would deliver to one of its controllers. When called, Basic.changeset
would actually receive %{"age" => "1", "date" => "2001-01-01"}
.
You could now type the following:
That's not very exciting, though it's interesting that you've gotten a Basic.SimplestParams.Tester
module that contains some test-support functions like params
(line 4).
We could use those params in tests:
That's fine, but it doesn't gain much. In fact, it's arguably worse than describing the parameters in the test, because the input values are visually far separated from the expected results. So let's move the expected results.
It has two fields, :age
and :date
. Each is processed ("cast", line 12) by transformations built into Ecto. The result is a structure. It will be marked as invalid if the :age
is a string that's not an integer or the :date
is not in proper ISO8601 format. Beyond that, all that's required is that each field have some value. (Without that, a missing or empty field would be allowed.)
All the code in this tutorial can be found at .
The module names the module under test (line 2) and notes that it's assumed to use the Ecto Classic workflow variant (line 3). There are other workflows. For example, I use a -style workflow that extends the Ecto Classic workflow. It has its own variant.
(The test uses the "flow-style" assertions from .)