So in this video, we're going to take a
simple Junit 4 test and convert it into a data driven or parametrized test.
The data driven test is very useful because it means that we can have a single
script, essentially, a simple path through an application, and we can.
Parameterize it with data to increase the coverage that we can get from the test.
So this is going to be an incredibly simple test.
You can see this test at the moment.
It basically says I have a private
variable called getversion, a variable called checkversion, the test
prints out what they are then asserts that the getversion is between one and five
inclusively, and the checkversion is between 11 and 15 inclusively.
So if I ran this now, it should pass, but it's not really data driven.
We have a set of data, but it's hard-
coded, we're not incrementing this over the life of the test.
So in order to do that, we need to make this a parametrized test.
So I'm going to do is, I'm going to make
this test @runwith and we'll make a parametrized dot class.
So this now is a parameterized test.
Now, it will probably fail if I run this. Yep.
So it's telling me that we have no public static parameters method on a class.
So I have no actual way of passing data into this.
So I need to create a method that will set up the data that we're gonna use.
So I need to create a method, I'll call it
public static version combos, and then I'll parametrize this.
Let's make this void just to start with.
It needs to return a collection of object
arrays, but we'll do that in just a second and parameters.
So IntelliJ has automatically made this at
parameters come in from at Parameterized to have the import coming in here because
we've already imported the parameterized runner.
So this version combo's method will become the method that returns the parameters.
So let's run this test now.
It doesn't actually return anything.
So this will probably throw an error,
but it might give us a clue as to what to do next.
Okay.
So this is saying that the version combo's method must return an iterable of arrays,
because what we're doing is the version combo's is creating the list of data that
we're gonna pass in as the parameters or data driving our test.
So this needs to be I will call it a collection
of object array.
Now, that's just to make it as generic as humanly possible.
So let's make this array actually do something.
So I'm going to, first of all, set up the data.
So I'm gonna make this a list
and its a list that's going to contain an object array.
I'll call this ARGs and it will and it will be a new arraylist.
Let's do the imports.
Enter. All right.
Now, if I just return ARGs then
syntactic, everything's correct, but there's no data to pass in.
So let's pass in some data here.
So rather than hard coding the get version 1 to 15, what I'm gonna do is I'm going to
have get version iterate from one to five and check version iterate from 11 to 15.
But they're going to be in nested loops.
So it will iterate twenty five times. Right.
So there we go.
So I have created nested loops simply to create multiple
versions.
So ARGs is a list and I'm adding to the ARG.
A new object array which contains the get version and the version.
So if I run this now, will it work?
The answer is no.
Because we have no way of getting this
data from the parameters into our actual test.
So if I run the test now,
Junit will probably tell me what is going wrong and what we have to do next.
Okay,
so you can see that this is saying "wrong number of arguments".
And the reason for that.
But you can see that we've run this test twenty five times.
So what it's done is it's taken the parameters and it's created all the.
The list with 25 items in it.
But we have no way of getting this into the test.
And that's because normally when we create
test classes, they don't have a constructor.
But when we create Parameterized tests, we need to create a constructor.
So I'll say public and I will pass in the data.
And here we have two INTs.
That's what I'm going to be passing in as my data.
Because that's what's in the object array.
So I'll say int get version and int check version.
And now I can see why I've got these parameters up here, these fields.
So I'll get rid of those hard coded values
and I will say this dot version is the version that we've just passed in.
And this dot check version is the version that we just passed in.
So, now, I have
a constructor on my test that takes two integers, these two integers are what I
created in my object array in the parameters method.
And remember I've put this in nested loops in order to
create a list of values which are coming through.
So here each one of these test execution's is using one of the list entries.
So if I run this test now, what we should be doing is generating
a list containing 25 items, which is one eleven, one twelve, one thirteen, etc.
, etc. two eleven two twelve.
So we're creating a combination of values in here.
Then when the test runs, it will print out what they are.
And just assert they're within limits.
So this test should pass now.
And we'll have created our first data driven parameterised test.
Great so they all passed.
And you can see that when I click on each
one of these tests, it says using get version one and eleven.
This next one, one and 12.
So we've created the list of items.
And that's what we used to do with J Unit 4 up until I think version 4.11.
But it's not necessarily very readable in the reports.
And lot people go, well, we need to add extra reporting
functionality into Junit to make it readable.
And we don't really, because what we've
got is the ability in the parameters to add a name.
And here, if I add in
zero and I'll make this better in just a second.
And one, what, this is gonna do it's gonna change the name of the test from the
index in the list of items to the values that we've passed in.
So now I'm expecting to see one and eleven one and twelve one and thirteen.
So let's try it and see.
Run the test.
So now you can see that by using the name
attribute on the parameters annotation, I can change the name of each test that is
executed to give us some indication of the data that's being used in the report.
So I'll make this better.
And we'll say using combo get version zerp and check version.
One, and now, this should be even more readable.
When we come through.
So let me run the test, and while this is running, let me explain.
So remember, what we've had to do
is we've had to give our test class A constructor because we're passing in the
data to the class, which means that if I added any more tests in here, it would run
all the tests in the class, but it would all be using the same data.
Now, to allow the tests to use the data, I
have put them in two fields, so we pass them in through the constructor.
Then I've stored them in fields so the test can access.
And the way that we create the data is through a static method on the class
which is annotated with @ parameters or @ parametrized dot parameters.
And this returns a collection of object
arrays where each item in the collection is an object array.
So we can have as many items in there as we want.
And the object array is all the values that we want to use.
If I want to make the test driven from a C
SV file, then I could have my versions combo method read from a CSV file.
Now in JUnit five, we have annotations to read CSV files.
And there is a library that you can add
for Junit 4 called JUnitParams, which adds that type of functionality.
But this is the most basic approach for creating a parameterized test in Junit 4.
The limitations are we don't have data sources for every test.
We have a data source for the test class and all the tests use the same data,
which means that if you want to have multiple data driven tests with different
data, you need to create a class for each of them.
And add them in. But it's relatively simple.
Once you get your head around and once you get your head around the notion that
you're building a list of object arrays and all your data goes in there.
That's pretty much all we have to do to
create data driven class in JUnit four and with later versions of JUnit four
when we use the name attribute, we have the ability to make our test execution
names much more readable for external reporting.