Parametrized tests with Spek


Everyone knows the situations when we have to check our system for various input. A good example would be a login/password validation performed both on front and backend.
There are many approaches to create a test code which covers all necessary cases:

1.  copy-paste methods (not recommended),

2. make many assertions in one test method (we can lose some valuable error info)

3. use parametrized test functionality bundled within test framework we use.
Keep in mind that there are more options available.

If you want to have several test cases in jUnit4, you have to use parametrized runner and add some methods with dedicated annotations, and implement method returning a list of parameters and expected output:

Pretty ugly, huh? A full example in Java can be found here: https://github.com/junit-team/junit4/wiki/Parameterized-tests

We can do better

Imagine, if we could write our tests like we write our code. Clear output, no annotation driven development, and no unnecessary static methods. That is were Spek comes to help.

Consider simple distance converter — we parse given distance in meters to desired unit.

value [m] displayed string
753 753 m
1337 1.34 km
15888 15.9 km
31270 31 km
51000 >50 km

It’s a simple case —the implementation is trivial. It only takes one switch or when and a function to round number with desired precision to solve this case.

Despite the fact, that the implementation is simple, we should prepare unit test it. Using Spek we can also write BDD style tests and prepare a specification for one approach.

Run this snippet and check results. We tested two cases, however, we are still repeating ourselves. It is as long and ugly as @Parametrized jUnit test or just test with many methods.

Spek DSL is a huge lambda expression, so we can use any Kotlin language features.

Let’s start with defining our test cases and expected outcome using Map<Double, String>:

Now we can use forEach{} to generate desired test cases:

Finally, we can make some assertion. A full example will look like this:

Conclusion

When creating unit tests we have to be sure that all (reasonable) cases are covered. In provided example (distance converter) we used Map<Double, String> and forEach{k,v -> } to parametrize our test and create on() ActionBody and it() TestBody in a stream. We have performed checks on each value, asserted expected outcome and displayed test result nicely in our IDE. We haven’t lost any valuable info, and we can add another test cases in clear Kotlin syntax.

Using Spek gives you the full power of Kotlin — you can write your tests just like you write your code and make use of language features.

I hope that you find this article useful, and it will help you look at parametrized tests in a different way.


Originally published on: https://blog.kotlin-academy.com


Leave a Comment