Assertions that read like English
This page describes functionality and usage of a small testing library called JSpec. JSpec was originated from ActiveJDBC project and was inspired by RSpec.
The grand idea
The idea is to replace "assert" language with "should" language and make it as close to English as possible. This forces the brain to work in a different mode, writing a "specification of behavior" for your program rather than "assertion" that the program works. The difference might seem subtle, but requires a different style of thinking and promotes true TDD/BDD - when specifications are written before implementation, sometimes even by different people.
JSpec uses 'should' word instead of 'assert'. Here is an example of an old style test:
1 2 3 4 5 6
The JSpec style of writing this test would be:
1 2 3 4 5 6
The result of executing either test is the same, but the style is completely different:
- The method name starts with "should", which implies that the functionality is not developed yet! It is very important to write tests with clear understanding of the requirements and describe a system "behavior" in code before implementation is developed.
- The expectation reads almost like an English sentence: "calculation result should be equal 4".
In the code above, you see the usage of
a() method. This method returns an object "Expectation", which you really do not care about, because it is never used directly. It is used as a form of a fluent interface and has all the
should..() methods for verifications.
All the three methods
$() return the expectation object and do exactly the same. They are synonyms of each other.
The reason for having three methods is to provide English words to make the expectation "sentence" sound better. Use whichever method that makes your assertion sound the best.
Numeric type indifference in
$() methods are numeric type agnostic. In JUnit this will fail:
while the two numbers are identical in value for all practical purposes, the JUnit assertion will fail just because the types are different, one being an Integer, and another a Long. The same test in JSpec using either 'a' or 'the' will succeed:
The only difference between the
it() method and
the() is that in the
it() method the tested object type and expected object type are parametrized with Java Generics. This means that they must be the same type:
Expect that the two objects are equal with the use of a standard
The great thing about this method is that it will check that the objects are the same type, has a protection for
null and will produce a good quality message in case objects are not equal. This code:
Will produce this message:
Test object: java.lang.String == <a> and expected java.lang.String == <b>
while this code:
will produce this message:
Test object: java.lang.String == <a> and expected null == <null>
As you can see, the messages not only provide values of tested and expected objects, but also provide their types, which is often important.
There are three dynamic boolean methods that are supported by JSpec:
For all three methods, the argument is an abridged boolean method of a tested class. This means that if there is such a class Person:
1 2 3 4 5
you can write an expectation in this style:
What happens here is that the JSpec will dynamically execute the method
person.isValid() and will evaluate its return value. If the value returned is false, the expectation is not met, and test will fail with exception.
Example for shouldHave():
1 2 3
and the expectation is:
The goal of this style of expectations to make them as close as possible to sound like an English sentence.
Expects that the tested reference is not null (or is):
In case the x is actually
null, the test will fail with:
org.javalite.test.jspec.TestException: Object is null, while it is not expected
Sets up expectation for a tested object's type:
If expectation not met, the error can be:
org.javalite.test.jspec.TestException: class java.lang.String is not class java.lang.Long
shouldBeA is a synonym of
shouldBeType, use either one for a better sounding sentence.
These are self-explanatory:
These methods are to check if the tested and expected references point to the same (or not) object.
Tests that an expected value is contained in the tested object. The tested object can be of the following types:
- Any object - the string representation of this object is tested to contain a string representation of expected value as a substring. For example, this will pass:
java.util.List- the tested list is expected to contain an expected object. For example, this will pass:
java.util.Map- the tested map is expected to contain an object whose key is the expected object. For example, this will pass:
1 2 3 4 5
shouldNotContain() is exactly the opposite of shouldContain().
Often times you need to ensure that some number before and after the operation is different. For instance, this could be a total count of specific records in a table, or a size of a list. Here is an example of using a difference expectation with JSpec:
1 2 3 4 5 6
In the code snippet above, the constructor of
DifferenceExpectation(..) is passed an initial value, and the method
exec() returns a final value. The initial and final are compared to be different at the end of a test. If they are the same, then the test fails. An example message:
javalite.test.jspec.TestException: Objects: '1' and '1' are equal, but they should not be
Using with other technologies
JSpec is really a few classes, and as such can be used with any other testing technology. Sometimes people use it outside tests, just to assert correct argument values passed into methods.
Here is a good Example of using JSpec and Cucumber.
Where to find
JSpec is packaged into JavaLite Common library, which is published into Maven Central.
Adding it to your project is easy:
1 2 3 4 5
Releases and versions of JavaLite Common are on the same schedule as ActiveJDBC.
How to comment
The comment section below is to discuss documentation on this page.
If you have an issue, or discover bug, please follow instructions on the Support page