I've been experimenting with ways to make writing generative integration tests a bit easier, and the resultant tests less cluttered with setup code and better at expressing their intent. Specifically I wanted to make creating and inserting records into a database as part of test setup a lot easier and less involved.
I've come up with something I'd appreciate feedback on, as I'm not sure if it's a good or a terrible idea! I would normally run a mile from introducing complex macros and magic syntax, and this is both of those. However I think it does make the tests a lot easier to write and read *once you've gotten used to its syntax*. You can see the code at https://github.com/rsslldnphy/test.calculus - the example project can be found in https://github.com/rsslldnphy/test.calculus/tree/master/dev/src/example, and the test for it in https://github.com/rsslldnphy/test.calculus/blob/master/test/example/forums/handlers_test.clj . The basic idea is to split the generation of test records from the setting up of the relationships between them and then their subsequent insertion into the DB, but have all three steps handled for you by a magic (shudder) `integration-test` macro. You end up writing tests that look like this: (tc/use-test-db th/test-db) (deftest forum-posts-test (tc/integration-test "get-posts" 10 ;; uses test.chuck/times for configurable number of test runs ;; 'fixtures' are specified first. these are records that will be ;; generated from user defined generators (specified elsewhere) and inserted into the DB before ;; the tests are run. [:users [dinesh aamira charlotte shonda hideo] :forums [funny-cat-gifs politics clojure-enthusiasts] :posts [my-cat resisting-trump macro-confusion cat-cafes parenthesis-overload]] ;; 'relationships' follow the fixtures. these trigger the use of ;; user-defined functions that set foreign keys/create the join table ;; records required to specify the given relationship in the db. [:member funny-cat-gifs dinesh charlotte shonda] [:member politics aamira shonda hideo] [:member clojure-enthusiasts dinesh aamira] [:author [charlotte funny-cat-gifs] my-cat] [:author [shonda funny-cat-gifs] cat-cafes] [:author [hideo politics] resisting-trump] [:author [dinesh clojure-enthusiasts] macro-confusion] [:author [aamira clojure-enthusiasts] parenthesis-overload] ;; 'generators' - any other arbitrary generators that are needed can be ;; specified here. these are not really needed for the below test, but are ;; just there as an example. [x gen/s-pos-int y gen/s-pos-int] (is (> (+ x y) x)) (is (> (+ x y) y)) (is (= (sort-by :post_id [macro-confusion parenthesis-overload]) (sort-by :post_id (h/get-posts (tc/test-db) clojure-enthusiasts)))))) The keywords in the fixtures section look up generators defined by the user - these can be arbitrary test.check generators (in the example project in the repo I've used Prismatic Schema, because we haven't yet made the leap to clojure.spec where I work... :-)). The keywords in the relationships section look up simple functions defined by the user. You can see examples of both these and the fixtures in the example project in the repo at https://github.com/rsslldnphy/test.calculus/blob/master/test/example/test/helper.clj As I say, I'm keen to get feedback. Is this a terrible idea or worth pursuing? Are there any pitfalls I should be considering? Does the syntax/structure of the integration test setup sort of make sense, or is it hopelessly confusing? Any ideas on how to improve it? Thanks for your time, Russell -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to [email protected] Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
