Redesigning JUnit Asserts
After reading about Behaviour Driven Development, using jMock for a while, and since I am very fond of Ruby’s core class APIs, I am sure the assertations of JUnit need a major overhaul.
This are the goals I have for the redesign:
- Make the code expressive and as readable as possbile. This means the code should look like plain english.
- Usability is more important than flexibility.
- Allow for much more poweful checks.
Usability is very important. The good thing is that it is easy to analyze how JUnit is used (download some test driven developed open source projects, grep for assertTrue, and there you have all the cases where JUnit’s asserts were not good enough :-))
I am playing around with a few ideas, and this is the API I am currently after:
Assertions Example Usage
public void testInt() {
int num = 4+1;
ensure(num).is(5);
ensure(num).either(4, 5, 6);
ensure(num).between(3, 10);
}
public void testDouble() {
double val = 4 + 0.4;
// an epsilon is mandatory when comparing double
ensure(val).is(4.4, 0.0001);
ensure(val).between(4.3, 4.5);
}
public void testArray() {
int[] a = { 1, 2, 3, 4, 5 };
ensure(a).contains(3);
ensure(a).size().either(5, 6);
ensure(a).contains(2, 3, 4);
ensure(a).contains().either(3, 10, 11);
ensure(a).contains().neither(6, 7, 9);
ensure(a).contains().any(3, 4);
ensure(a).contains().all(3, 4, 5);
ensure(a).isSorted();
ensure(a).isUnique();
}
Starting point is always ensure(). You put in the actual value, then execute some operations that modify the following constraint check, then the last command is the constraint check. The last command is always the constraint check, so you can only do one check per line of code. That’s not as flexible as jMock, but it is simpler and more readable and good enough.
Technically all this is very doable. Probably quite a bit of work, and most likely requires a code generator since lots of code is almost the same but not reusable (e.g. arrays for primitive data types), but that’s not a problem. I have done a few simple feasibility studies and I don’t see a big problem with this interface.
Please tell me what you think about this!
Updates
From time to time I will update this page with progress reports, until I have something that is stable enough to give away.
- 2006-08-05
- I have started developing this. So far I am very happy with it, its a fun project to implement
I will probably create a project on sourceforge and opensource it, but I am not sure about the licence.



August 3rd, 2006 at 11:48 am
Very interesting idea! That would be a nice way to provide many of the standard checks everyone needs.
What I don’t like is that you kind of “abuse” the methods to make the code look more like plain english:
- the method “ensure” wouldn’t ensure anything but return some wrapper (I guess).
- a method “contains()” without a parameter looks very weird because one would expect the object to test here.
Why don’t you use something like:
object(a).contains(neither(3,4));
In my opinion that wouldn’t be much less readable but would look more like Java.
Another thing that comes to mind: how would you handle user defined objects?
Jens
August 3rd, 2006 at 3:45 pm
Hi, thanks for your comment! You are right that this is not really the typical java style.
- object() is not the right choice either, because I am not objecting anything
- The syntax with contains(neither(3,4)) is a bit cleaner, but then I have the problem that I need lots of other static methods. Currently only ensure() needs to be a static method.
I think it should not be difficult to write ensure() methods for user defined objects. Just write the static method ensure(), and then you can reuse the functionality of the other checker implementations. e.g. if you have a special collection you could easily provide an ensure().size() method where you call your own size method but return an already available NumberChecker so that you can call ensure(x).size().is(100);
August 3rd, 2006 at 10:01 pm
Yeah, you’re right! object() wasn’t that good idea!:-)
Why do you need static methods at all? The problem with static methods is that you can’t overwrite them. I thought you would implement a new TestCase class with a method “ensure()”?
I agree with you that you would need too many methods for contains(neither(3,4)). Maybe containsNeither(3,4)?
I’ve still got the feeling that user defined objects are a problem. Of course it would be easy to write my own ensure() but I have much more to do than I have when using JUnit.
E.g. if I have got a class “Candle” and want to test if a Candle object is burning I would do the following with JUnit:
assertTrue(candle.isBurning());
For this test I have to write one class with one method.
If I want to test the same with “ensure(candle).isBurning()” I need at least 2 classes (the test case and the wrapper for Candle) and 2 methods.
Is the benefit of having a nice looking test really worth having to do the double amount of work?
August 3rd, 2006 at 10:29 pm
I would like to have static methods because I like the way junit4 uses the import static:
http://www-128.ibm.com/developerworks/java/library/j-junit4.html
this way it would be very easy to use the ensure() in your existing unit tests, just import the methods and you can use them. No need to extend TestCase.
I was also thinking about the containsNeither syntax, but then you quickly get a hell of a lot of different methods, and it is difficult to reuse code.
instead of
ensure(candle).isBurning()
you can use ensure(candle.isBurning()).isTrue()
With the basic checks you can also write
ensure(candle.length()).between(30,34)
so you do not really always need to write custom test classes.
January 4th, 2007 at 1:38 pm
If you decide to use Java 5 you should use varargs for the either() / neither(). In case you don’t have experience yet with varargs:
Instead of overloading either() like this:
boolean either(Object e1);
boolean either(Object e1, Object e2);
With varargs:
boolean either(Object… e1);
(this is like passing a array into the function)
January 4th, 2007 at 1:43 pm
Oops, forgot a part of my message.
If you put it on sf.net I’d probably use it! I’m a big fan of jUnit and I really like the way you are making it more readable. This could also be usefull in the IT company I work for, maybe some testers could write their own testcases with this.
So please open-source it… and don’t forget to notify me when you do! Btw. the Belgian branch of our company is working on a jUnit project too:
http://unitils.sourceforge.net/
Maybe the two could then be integrated if you(/and them) want.
January 4th, 2007 at 7:50 pm
Hi Roy, the ensure4j library is shaping up quite nicely. I am using Java 5 and am already using varargs whenever appropriate
The ensure() syntax has already proven to be very useful, e.g. I have added statistical tests that make it possible to e.g. verify the quality of optimizers.
I would love to make this open source, but I have developed it at work while working on another project so I am not sure if I can convince my boss to do this.