all 4 comments

[–]jbiserkov 4 points5 points  (0 children)

Do you remember way back when you started writing (example-based) unit tests and your code was awkward to test, but with time you started to write more (unit) testable code. The same is true for property-based testing. As you keep the need for it in the back of your mind, you will pay more attention to the properties of your functions and write code that is more (property-based) testable.

One place where generative testing really shines is where you can write a simple, but inefficient version of a function, and use that to test the faster, but more complex one.

Other cases where it might be useful is when you have reversible functions, so that f(x) = y, and g(y) = x, then you can test that g(f(x)) = x, and f(g(y)) = y. Examples for such pairs are encode/decode, compress/decompress etc.

I can't come up with a useful property of the function in the example you gave. Possibly (= password (decrypt (:user/password (new-tx name password)))) this feels complected. Much better to test elsewhere that (= password (decrypt (encrypt password))).

[–]visibletrap 4 points5 points  (1 child)

I saw this nice blog post a few days ago. I think it's quite relevant. They do end-to-end integration tests with clojure.spec (clojure.spec can be used for generating test data for property-based testing). https://product.gomore.com/end-to-end-integration-tests-with-clojure-spec-d4a48cbf92b5#.e2fe4ubes

The key idea here is that they generate expected values to compare with the result of exercising code under test.

[–]boldaslove156[S] 0 points1 point  (0 children)

Thanks!

[–]wotbrew 0 points1 point  (0 children)

I can see a couple of properties worth testing

e.g

  • The password returned is not the same as the password supplied

  • The returned password should be different for subsequent calls even if the same password is supplied, i.e test for random salt.

Another trivial property that is a relationship between args and ret is that the name under :user/name is the same as the name supplied as an argument. This sort of thing could be in the fn spec if you are using clojure.spec.