- In this section, we're going to see
how and why to define parameterized tests.
So, first of all, to understand the need
for parameterized tests, we're gonna have a look
at some code in the ParameterizedTests folder.
I'm gonna show you a simple JavaScript file
with an add function, which just adds two numbers together.
And then I have some tests in this file
which calls the add function several times
with different inputs
and with a different expected result each time.
So let me show you the code first.
So in JsTdd lesson three in the ParameterizedTests folder.
I fill up that folder in the code editor
that it looks like this.
We have a simple calc.js.
A very simple add function, adds two numbers together.
And then I have four different versions
of a test showing how to parameterized it.
So, first of all, we'll have look
at the kind of brute force approach in calc1.test.
So in here, I import the add function.
Have a look, I've got three tests.
The first test, it calls the add function
with 10 and 20 and it should give me back 30.
The second test is exactly the same
except that it has different inputs,
10 and -20 with a result of -10.
The third test is also exactly the same
except with different inputs and a different result.
So what we see there is a certain amount of duplication.
The similarity between the tests is quite striking.
The only thing that's different in each case is the numbers.
And clearly that's not a good idea.
You shouldn't be duplicating code like that.
It's never a good idea to have duplicate code.
So in a situation where we basically have the same test
but to run it multiple times with different inputs
and a different expected result,
rather than having actually three separate tests,
justify one test and parameterized it.
And that's what I've done here.
You can call test.each and then you give it an array
and each array specifies a different invocation of the test.
So this test here in black is going to be executed
once with those inputs,
a second time with those inputs,
and a third time with those inputs.
I've only written the test once,
but it's going to be executed three times.
So this test, it has a description
and it has prompted as n1, n2, expected.
These are the values that are going to get passed in.
So the first time, a test will be executed.
10 will be passed into n1, 20 into n2, 30 into expected.
And adds 10 and 20 and the expected value should be 30.
And then it repeats the test again.
It runs the same test, second time.
Passing a different set of values, 10 into n1,
- 20 into n2, -10 into expected.
So the second test is driven by the parameters
and then it runs a third time.
The same code, written once, but run three times.
We'll now take n1, n2, expected.
So that's a much better way of doing.
It's much less duplication.
I should run it just to make sure that it actually works.
So in my command window, npm run test parameters.
And the name of my test file is calc2.test.js.
So it ran my test code three times
with a different set of inputs
and hopefully they should all pass.
There we go.
Unfortunately, I mean, it does work
but when it ran the test,
each time it ran the test, it displayed the same message,
add two numbers to give correct result.
So basically it displayed the same message
or the same title for the test every time it ran it.
So if you wanna parameterized the string as well
to display a more useful message for each test run.
You can do that like this.
In the name of the test, you can define the test
as an interpolated string with backticks
and then you can use a %d and it'll substitute the value
for n1 into here and n2 and expected.
So that means that that as we run the test three times,
we'll be using these embedded specifiers %d
for decimal number.
Will give us a different message name
each test that gets executed.
So let me show you that.
So I'm good to run calc3.test.js.
The tests will be run as before,
but what's gonna be different is the titles of the test.
Instead of having the same title
be displayed every time like before,
now it displays %d n1,
%d n2, %d expected.
So each run has different inputs
for n1, n2, and expected.
So the titles for the tests are more informative
so that's better, isn't it?
If one of these tests didn't work,
now you've got a better idea,
which set of inputs failed
and that would lead you to figure out
what the bug was in your code.
So that's an improvement
using these kind of embedded parameters
to give us a more meaningful name for the tests.
There's actually a different syntax you can use
called an interpolated or Tagged Template Literal Syntax,
where we have an interpolated string.
test.each basically takes one giant string
and this string specifies,
well, the first line basically is one string
where it specifies the values for the n1 parameter,
the n2 parameter and the expected result
for the first run and for the second run,
and for the third one.
The dollar curly bracket syntax here
is ECMAScript interpolated string.
So it basically evaluates that as a number
and it passes in as n1.
It evaluates this as a number and it passes as n2.
And it evaluates this 30 as a number
and passes it as the exp, as in expected.
So the first row in this giant string
that starts there and ends there,
the first string is the name of variables.
It's actually going to, what's gonna happen
is every time it's gonna grab the next line.
It'll grab the next line.
So $10, $20, $30, and it'll put these into an object.
It'll create an object
with a property called n1 with a value 10,
a property called n2 with a value 20,
and property exp with a value 30.
So we have an object created for us
with properties n1, n2 and exp .
And that object then gets passed into the test function.
And in this text function, it receives an object
and it uses destructuring.
This is destructuring syntax.
This, it receives an object
and it extracts the n1 property into this variable.
And it extracts the n2 property, 20, into that variable.
And it extracts the exp property, 30, into that variable.
And notice, the string here is slightly
different syntax as well.
We say $n1.
So that would be the value of the n1 parameter, 10.
$n2 is the value of the n2 parameter, which would be 20.
So it's time through.
And the $exp is obviously the value of the exp parameter,
which would be 30.
So there's a slightly different syntax here
for building formatted string
and a slightly different syntax here
for grabbing access to the values.
So this function will be called.
The first time an object with an n1, n2, exp property
set to these values, 10, 20, 30.
Again, it'll call the function a second time,
pass in an object with an n1, n2, exp property.
So it'd be 10, -20, -10 and so on and so forth.
So the result would be the same, but it's a different way.
I actually quite like this syntax, to be honest.
It's quite clear.
It's quite tabular.
It gives us an idea of the purpose
of each row in the string.
We should actually run it as well, I guess,
to make sure that it does actually work.
So I'm going to run calc4.
So I'm looking here to see if the messages
for the tests are meaningful and if the tests actually pass.
Okay. So yes, grab the value of the n1 property, n2, exp.
Displayed suitable error messages and the tests are passed.
So personally, this is the way I would prefer
to declare a parameterized test function
using this Tagged Template Literal Syntax,
which looks quite cool to me.