Using logic programming (Clojure's core.logic) for test data manipulation and generation
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

The goal of this project is to make it as easy as possible to construct test data, including hierarchical data with constraints on how datum X can be used with datum Y.

User documentation

Easy lookup of named tabular data

So, for example, suppose I have animals and medical procedures:

(data [animal :by :name :with-selectors]
      {:name "betty" :species :bovine :legs 4}
      {:name "hank" :species :equine :legs 4}
      {:name "jake" :species :equine :legs 3} ; poor jake
      {:name "dawn" :species :human :legs 2})

(data [procedure :by :name :with-selectors]
      {:name "hoof trim" :species-rule :equine-only :days-delay 0}
      {:name "superovulation" :species-rule :bovine-only :days-delay 90}
      {:name "physical exam" :species-rule :all :days-delay 0})

From this, we can auto-construct selectors that let us easily ask for the names of data that satisfy constraints.

  (animal?> :legs 4) ;; ["betty" "hank"]
  (one-procedure?> :days-delay 0) ;; "hoof trim"

Once you have names, you can use the tables to populate a database or whatever.

Groups of names that satisfy constraints.

Let's say the permitted?? relation/goal succeeds when a particular procedure is permitted on a particular animal. So, for example:

(permitted?? "hoof trim" "hank") ;; succeed
(permitted?? "hoof trim" "dawn") ;; fail

Now we can ask for pairs that are permitted:

(permitted?>) ;; [["hoof trim", "hank"], ["superovulation" "betty"]], etc.
(one-permitted?> :procedure "hoof trim") ;; ["hoof trim" "hank"], etc.

Hierarchical data

The app from which these examples are drawn is largely about reservations, which contain one or more (permitted) procedure/animal pairs. I want to show a "picture" of the "shape" of reservation I want, and then let an engine fill in the blanks.

For example, the most common reservation used in the tests is one group with one procedure/animal pair. In many many cases, I don't actually care which procedure and which animal I use. I want to describe it like this:

(reservation?> [- -] [- -])

... and get back a data structure something like this:

([["hank" "hoof trim"] ["betty" "superovulation"]] ...)

Then a database-population routine (that would look extremely like the one that already exists to add a reservation from json data) would take over.

Sometimes you'd want constraints. Some of those can be expressed in abbreviated form. Suppose I want two pairs, the first containing Hank the Horse and some appropriate procedure, the second containing a cow. That would look like this:

(reservation?>  ["hank" -] [{:species :bovine} -])

I have a prototype of this working. The big question is whether it's a plausible stunted framework: one that's not so universal that it's too hard to learn and too fiddly to work with, but that doesn't require so much customization that it's not worthwhile?

Another question: Logic programming is esoteric. The framework aims to write most of a core.logic query for you, but you need to provide some help. Can you use this framework without having to be an expert in core.logic?

And: is Clojure a large enough language community? one that builds the sort of apps that need sophisticated test data generation?


Copyright © 2012 Brian Marick

Distributed under the Eclipse Public License, the same as Clojure.