Conversation
mhanberg
left a comment
There was a problem hiding this comment.
I'll have to pull this down and play around with it, nice work so far!
|
Does it make sense to organize the prop tests based on "properties" of the code rather than by function? like, the property is that inputs can be unified and dumped back and forth, so the stream data generator generates random arbitrary inputs/schematics and ensures that I assume it's currently broken up by function because you were just incrementally working through them, but before we merge it is worth considering whether combining them into fewer properties makes sense. |
| |> StreamData.one_of() | ||
| end | ||
|
|
||
| def from_schematic(%Schematic{kind: kind}) do |
There was a problem hiding this comment.
I think this is closer to what we want.
I think there should probably be some function like gen or generate that takes a schematic, and then spits out the stream data equivalent.
I think you still need to move the stream data generator for the blueprintable map schematic into this.
Then, I feel like you would be able to to more or less have a single property that generates an arbitrary schematic that can be any depth and combination of them, and test that it unifies and dumps back to itself.
There was a problem hiding this comment.
And this functionality can probably be re-used to make the user facing stream data API
There was a problem hiding this comment.
i just added something that is getting towards this idea. it's a little rough, and doesn't cover key transformation for maps, but with this is place we can probably drop a lot of the smaller property tests that i wrote along the way to this. i'll take a look at that tomorrow
| check all( | ||
| {blueprint, input} <- | ||
| StreamData.bind( | ||
| StreamData.map_of(StreamData.binary(), Generators.schematic(), min_length: 1), |
There was a problem hiding this comment.
map schematics can technically have any value as a key in the blueprint, so we would want to expand this generator to reflect that.
We'll also want it to generate map blue prints that reflect the key transformation capabilities: https://hexdocs.pm/schematic/Schematic.html#map/1-transforming-keys
yeah, i think that that makes sense. i didn't jump into this with a wholistic understanding of everything, so yeah i was just working through incrementally. now that i have a better understanding of the shape of the whole thing, i think this makes sense |
| property "input |> unify |> dump == input" do | ||
| check all({schematic, input} <- Generators.schematic_and_data()) do | ||
| {:ok, input} == | ||
| unify(schematic, input) |> then(fn {:ok, result} -> dump(schematic, result) end) | ||
| end | ||
| end |
There was a problem hiding this comment.
will this replace the other properties?
There was a problem hiding this comment.
most of them, i think. i'm gonna comb through today and remove the ones that are definitely overshadowed by this
There was a problem hiding this comment.
replaced a bunch of existing properties that were superseded by this one. still a few remaining, but i suspect only one or two besides this are worth keeping. lmk if you feel differently
|
One annoying comment, can you add stream_data to the formatter.exs import deps and then remove the parens from all the 😅 |
haha sure thing. not "annoying" btw, i totally get it |
|
@clark-lindsay Can you rebase this and then I'll review |
WORK IN PROGRESS: may end up removing the tests that the new property-based tests overshadow, which would do away with the awkward naming convention that i started with. additionally, i wrote the generators in the `test/support` directory after the JSON spec because it seemed to match well with the data types supported by `schematic` right now (w/ the exception of `tuple`), but this may just be incidental
WORK IN PROGRESS: there are a few rough edges here, so i'll record my
current thoughts on them:
- i'm still not sure how valuable a separate module for `StreamData`
generators is, but right now it feels like it improves the
organization of the test code
- currently a `list/0` schematic can match a non-homogenous list,
whereas any call to `list/1` must match the given schematic
homogenously (but you **could** pass a `one_of` schematic...)
- is this the right design? i think it ***is right***, but i left
myself a "TODO" to think about it some more
- should property-based tests be written to describe the properties
of the code for the failure paths? or is that better left to
hand-written edge case unit tests?
also extended some of the data generation in the `Generators` test support module
- better reporting from `mix test` - easier to notice/find/grep-for tests are property-based - automatically tags the tests, so one can use `mix test --only property` to target _just_ the property-based tests
also extend and start to document support generators, in support of ongoing test expansion and improvements
i don't entirely understand why there was a call to `Map.delete/2` in the `unify` definition for the `map` schematic, but with it in place i was dropping `""` keys when `dump`-ing. removing the call has no effect on any other tests, and so i believe that it's not necessary, ***but*** i may have written the test incorrectly and misunderstood the desired behaviour...
i still can't think of a good way to generate tuples, but i at least want the schematic `kind` accounted for in the tests in the meantime
thanks @motch for the _much_ improved name idea
the `property` "input |> unify |> dump == input" supercedes most of the existing `property`s in the test file, which were written as stepping stones for me to understand the behaviours and design of the code to work towards more general properties that could be tested remaining `property`s that were not deleted still have cases that are not covered by the aforementioned "input |> unify |> dump == input" test, and some `TODO`s have been added to address the generation of schematics and data so that these `property`s will become redundant and then be removed
also:
- extended the schematics that can be generated from
`Generators.schematic_and_data/0`
- removed a `property` that is now superseded by the "input |> unify
|> dump |> input" `property` test
- added a few specific cases to the `tuple/2` example-based tests that
reproduced the bug found in the `unify` callback from `tuple/2`
Co-authored-by: Mitchell Hanberg <mitch@mitchellhanberg.com>
1e02862 to
12d21ea
Compare
|
|
||
| ```elixir | ||
| iex> schematic = tuple([str(), int()]) | ||
| iex> schematic = Schematic.tuple([str(), int()]) |
There was a problem hiding this comment.
did you say you could remove the Schematic. part?
|
Thanks! |
Description
Adds property-based tests with StreamData to improve confidence in the test suite and make the library more reliable and easier to extend.
Most of the property based testing is condensed around a single
propertytest that asserts that an arbitrary{schematic, data}tuple, where the data and the schematic are compatible and will successfullyunify/2, satisfies the following pseudocode:data |> unify |> dump == dataAs this is a draft, i am open to any and all feedback
Closes #8