PropSchema v0.3.1 PropSchema
An extension on Ecto.Schema
used to generate property tests. Schema can be further augmented
based on additional options, which will be read by the corresponding PropSchema.Executor
module
to generate tests.
Example
prop_schema "example" do
prop_field(:example_string, :string, string_type: :alphanumeric, required: true)
prop_field(:example_int, :integer, postive: true, required: false)
field(:example_float, :float)
end
This declares the schema "example"
with three fields: :example_string
, :example_int
, and :example_float
.
Property test will be generated for :example_string
and :example_int
but, since :example
is declared using
the regular Ecto.Schema.field/3
, a test will not be generated for it.
Adding these are equivalent to writing these tests:
property("valid changeset") do
check(all(map <- StreamData.fixed_map([{"example_int", StreamData.one_of([StreamData.integer(), StreamData.constant(nil)])}, {"example_string", StreamData.string(:alphanumeric, min_length: 1)}]))) do
changeset = PropSchema.ExampleModule.changeset(struct(PropSchema.ExampleModule), map)
(fn changeset ->
if(not(changeset.valid?())) do
Logger.error("Test will fail because: #{inspect(changeset.errors())}")
end
assert(changeset.valid?())
end).(changeset)
end
property("valid changeset - missing example_int") do
check(all(map <- StreamData.fixed_map([{"example_string", StreamData.string(:alphanumeric, min_length: 1)}]))) do
changeset = PropSchema.ExampleModule.changeset(struct(PropSchema.ExampleModule), map)
(fn changeset ->
if(not(changeset.valid?())) do
Logger.error("Test will fail because: #{inspect(changeset.errors())}")
end
assert(changeset.valid?())
end).(changeset)
end
end
property("invalid changeset - missing example_string") do
check(all(map <- StreamData.fixed_map([{"example_int", StreamData.one_of([StreamData.integer(), StreamData.constant(nil)])}]))) do
changeset = PropSchema.ExampleModule.changeset(struct(PropSchema.ExampleModule), map)
(fn changeset ->
if(changeset.valid?()) do
Logger.error("Test will fail because: No errors")
end
refute(changeset.valid?())
end).(changeset)
end
end
I you would like to see what tests are being generated for your schema, use the mix task:
$ mix prop_schema.print <module> [options]
Docs can be found here: Mix.Tasks.PropSchema.Print
Or for a more realistic example see example: module, properties, and generated tests.
Link to this section Summary
Functions
Declares a field in __prop_schema__/2
which will either be the name
with "_id"
appended or the value of the :foreign_key
option.
A UUID generator is provided for uid ids
High school english class time! prop_embedded/1
is to prop_schema/2
as Ecto.Schema.embedded_schema/1
is to Ecto.Schema.schema/2
Declares a field in the schema, processes it for use in PropSchema.Executor
and then passes it through to Ecto.Schema.field/3
. See prop_schema/2
for examples
Declares a field in __prop_schema__/2
which corresponds with a provided generator that will build the list of associated structs for you.
The only addition to the normal Ecto.Schema.has_many/3
call is the :additional_props
option which will tell the generator where
to find the additional props for building the associated structs
Declares a field in __prop_schema__/2
which corresponds with a provided generator that will build the associated struct for you.
The only addition to the normal Ecto.Schema.has_one/3
call is the :additional_props
option which will tell the generator where
to find the additional props for building the associated struct
Declares a field in __prop_schema__/2
which corresponds with a provided generator that will build the list of
associated structs for you. The only addition to the normal Ecto.Schema.many_to_many/3
call is the :additional_props
option which will tell the generator where to find the additional props for building the associated structs. The
associated struct’s __prop_schema__/2
results will be modified so as to not generate it’s associated many_to_many
structs due to the endless recursion that would cause
Declares an Ecto.Schema
with additional options that are used to generate property tests
using PropSchema.Executor
Link to this section Functions
prop_belongs_to(atom(), module(), Keyword.t()) :: PropSchema.Types.ast_expression()
Declares a field in __prop_schema__/2
which will either be the name
with "_id"
appended or the value of the :foreign_key
option.
A UUID generator is provided for uid ids.
prop_embedded([{:do, PropSchema.Types.ast_expression()}]) :: PropSchema.Types.ast_expression()
High school english class time! prop_embedded/1
is to prop_schema/2
as Ecto.Schema.embedded_schema/1
is to Ecto.Schema.schema/2
Examples
prop_embedded do
prop_field(:example_string, :string, string_type: :alphanumeric, required: true)
prop_field(:example_int, :integer, postive: true, required: false)
field(:example_float, :float)
end
prop_field(atom(), atom(), keyword()) :: PropSchema.Types.ast_expression()
Declares a field in the schema, processes it for use in PropSchema.Executor
and then passes it through to Ecto.Schema.field/3
. See prop_schema/2
for examples.
prop_has_many(atom(), module(), Keyword.t()) :: PropSchema.Types.ast_expression()
Declares a field in __prop_schema__/2
which corresponds with a provided generator that will build the list of associated structs for you.
The only addition to the normal Ecto.Schema.has_many/3
call is the :additional_props
option which will tell the generator where
to find the additional props for building the associated structs.
prop_has_one(atom(), module(), Keyword.t()) :: PropSchema.Types.ast_expression()
Declares a field in __prop_schema__/2
which corresponds with a provided generator that will build the associated struct for you.
The only addition to the normal Ecto.Schema.has_one/3
call is the :additional_props
option which will tell the generator where
to find the additional props for building the associated struct.
prop_many_to_many(atom(), module(), Keyword.t()) :: PropSchema.Types.ast_expression()
Declares a field in __prop_schema__/2
which corresponds with a provided generator that will build the list of
associated structs for you. The only addition to the normal Ecto.Schema.many_to_many/3
call is the :additional_props
option which will tell the generator where to find the additional props for building the associated structs. The
associated struct’s __prop_schema__/2
results will be modified so as to not generate it’s associated many_to_many
structs due to the endless recursion that would cause.
prop_schema(String.t(), [{:do, PropSchema.Types.ast_expression()}]) :: PropSchema.Types.ast_expression()
Declares an Ecto.Schema
with additional options that are used to generate property tests
using PropSchema.Executor
.
Field Declaration
When a field is declared with prop_field/3
it will add the extra values as conditions for generating property tests.
It is possible to declare a field just by using Ecto.Schema.field/3
however PropSchema.Executor
will
not know about it, and tests will not be generated for that field.
Examples
prop_schema "example" do
prop_field(:example_string, :string, string_type: :alphanumeric, required: true)
prop_field(:example_int, :integer, postive: true, required: false)
field(:example_float, :float)
end