Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do Midje and Speclj compare? [closed]

Tags:

clojure

Both look reasonably good. I'd like to understand what each library is particularly good at or lacking, especially for testing of web applications.

like image 323
clizzin Avatar asked Oct 17 '12 06:10

clizzin


1 Answers

I haven't used speclj, and I was the first author of Midje. One point that hasn't been mentioned by others is that Midje tries to exploit differences between functional and object-oriented languages.

One difference is immutability. Because most functions depend only on their inputs, not on contained state, the kind of truth statements you make about them are different in feel than their object-oriented counterparts. In OO testing, you make examples of the form: "given this history and these inputs, this method produces such and so."

It would seem that examples in a functional language would just be simpler ones: "given these inputs, this function returns such and so". But I don't think that's quite right. I think the other functions in the system play a role analogous to state/history: they're one of the things you're trying to get intellectual control over. Functions and their relationships are the things you want the tests to help you think clearly about.

For that reason, Midje is written under the assumption that a sweet development process involves saying:

  • What do I want to be true of this function? In the world of the system, what's a good way to think of what this function does?
  • In the process of doing that, what other functions would be useful---would capture an important part of the domain---and what truth statements do I want to make about them?

And then, in typical mockist style, you develop roughly top-down or outside-in, allowing for the inevitable iteration as you recover from mistakes or have better ideas.

The end result is to be a big pile of functions, with their interrelationships documented by the tests or (as Midje calls them) the "facts" about functions and the functions they depend on. Various people have commented that Midje has a Prolog/logic programming feel to it, and that's not an accident. As always, tests are examples, but Midje tries to make them read more like truth statements. That's the justification for its only actually innovative feature, metaconstants. Here's an example of them:

(fact "right changes the direction, but not the position"
  (right (snapshot north ...position...)) => (snapshot west ...position...)
  (right (snapshot east ...position...)) => (snapshot north ...position...)
  (right (snapshot south ...position...)) => (snapshot east ...position...)
  (right (snapshot west ...position...)) => (snapshot south ...position...))

In this case, the actual position is irrelevant to what's true about the function right, except that it never changes. The idea of a metaconstant is that it is a value about which nothing is known except what's explicitly stated in the test. Too often in tests, it's hard to tell what's essential and what's incidental. That has a number of bad effects: understanding, maintainability, etc. Metaconstants provide clarity. If it matters that a value is a map or record that contains the value 3 for key :a, you say that explicitly:

(fact
  (full-name ..person..) => "Brian Marick"
  (provided
     ..person.. =contains=> {:given-name "Brian", :family-name "Marick"}))

This test is explicit about what matters about people---and also explicit about what doesn't matter (anything but the two names).

In math terms, Midje is trying to let you make statements like "for all x where x..." while still being a test tool rather than a theorem prover.

This approach was inspired by "London-style" mock-heavy TDD of the sort described in Growing Object-Oriented Software, which is the approach I usually use in writing Ruby code. But it's turned out to have a pretty different feel, in a way that's hard to describe. But it's a feel that needs more tool support than just with-redefs.

The upshot is that Midje is in part an attempt to find a style of functional TDD that's not just a port of OO TDD. It tries to be a general-purpose tool, too, but it's semi-opinionated software. As Abraham Lincoln said, "Those who like this sort of thing will find this the sort of thing they like."

like image 115
Brian Marick Avatar answered Sep 18 '22 12:09

Brian Marick