Everybody has gone this is Caleb with slopes dot com and in this video we're going to talk about unit
testing of course but I'm going to show you a project that has already been built and we're basically
going to take that project and add in unit tests to make sure that it's future proved in a way so that
if a new dev were to come on all of our tests would pass and if they added anything that broke that
we would know.
So we're going to go ahead and pull up on our project here.
And it's called the wall calque Aroney.
I don't really know why I named it that but that's what it's named.
And basically it's a simple calculator application.
It's not perfect.
You know it doesn't do decimals yet there are some things that we can expand upon but for the most part
it works you know forty five minus six thirty nine eight times ten.
Eighty.
You know it works for the most part.
Decimal numbers are not yet enabled.
That will be something in the future.
But what I'm going to do is I'm going to walk you through the project really quickly and then we're
going to go ahead and integrate some tests for our calculation manager model.
So let's go ahead and take a look.
Basically our UI you just saw it it has quite a few buttons and a label and a nice little picture of
mountains in the background Dubbs.
Get it.
Mountains anyway.
And so then inside here we have a ton of Iby outlets for all those buttons we have as you know Iby actions
for the number buttons AC button operand button for you know plus minus plus minus.
Multiply and divide and then one for the equals button.
Then we basically create a calculation manager object and we instantiate it in feuded load and we use
the calculation manager to basically do everything regarding numbers and calculations.
OK it's its own little class.
So inside the calculation manager we have a couple of properties we have value a value b k we use that
you know 12 plus 6 value would be 12 value B would be 6.
The operand comes from an enumeration which we'll talk about in just a second and then we have what's
called value entry array.
So there are a few functions in here.
And the first one is called insert.
Basically if value A is equal to zero which it is initially we set value a to be the value that's passed
in.
So let's say we type 12.
We push enter.
That's going to set value.
Then if I come by and I push six value is already equal to 12.
So then it's going to go ahead and set value B to that value which is pretty cool.
So then we have a function in here called Set which basically just sets the operand.
So if we type you know 12 and push Plus set up Rand gets called and the current upper end gets set to
addition and then we call a function called set values.
We'll get to that in a second.
Basically append is a function that's going to append a value to our value a.a.
We'll talk about that as well.
Clear values does what you might think.
It's basically going to be just removing everything it clears the array and it sets all the values back
to 0.
That's useful when pushing the AC button.
And then this function is called the string of five values because of course we're using a label so
we can't put an integer directly into a label so we convert it into a string.
All right.
So then we have the set values function which basically begins with a value string.
Then we take our value a.a which if you look is of type int case we have a bunch of integers.
Basically what we're doing is we are appending each value in that array as a string.
And then we're appending the next character to the same string until we basically have a string of just
the number values that we typed into the calculator.
So it is a string though.
And then what we do is we take the int value.
Basically we take the value string we forecast it as an int and we pass in that value.
Then we clear out the array so that we can have the next value come in of course.
Calculate basically takes all the information and returns a particular value for either add subtract
multiply or divide.
And like I said before the operand Inam is just add subtract multiply and divide and they have number
values just that I could basically identify them easier with a particular value k or I guess with a
button tag in the storyboard.
So that is that.
And now we're going to go ahead and add our test cases really quickly.
And of course you can do this two ways you can either create a new project like so click Create new
project single view app give it a name and then all you have to do is tick.
Include unit test and it'll automatically include a testing target for you.
Or alternatively you can just go up to here type new target and then you're going to scroll down until
you find iOS unit testing bundle and it's common for you to basically you know type your project name
and then follow that up with tests.
That's it.
So it already does this automatically for you.
But if your project was named something different you could change it.
But anyway once you're done click Finish.
And of course that will pop up right here.
Open it up and you'll see it presents you with a swift file and it's called Wall Kelk Aroney tests.
And of course this is for testing the entire project.
But we're not going to be doing that.
We're going to be writing tests for our calculation manager first anyway.
So what we're going to do is we're going to right click Create a new file and it's going to basically
be a unit test case class.
So click that and we're going to go ahead and name it calculation manager tests and then click Next
save it and then basically we can get rid of this old one.
We don't need it anymore and you get rid of that bad boy.
And here we are.
So we have successfully imported X-C test.
We have successfully created a class called calculation manager tests and we have basically inherited
from X-C test case there are two functions here set up and tear down.
Like it says we're going to put set up code here.
This method is called before the invocation of every test method in the class so then we have tear down
like I said earlier tear down code basically rips all of the code down at the end.
So it's a good way to basically reset the state so that you're starting with a fresh state every test.
So we are given to test examples from the beginning we're not going to use these.
But what I want you to know is there is something that is the same about both of these and they both
begin with test that word is a key word and that's how X code knows that a test is beginning.
So if you don't type this it's basically going to register it as an ordinary example.
So if I try to build this you'll notice that little diamond goes away and that diamond is important.
So if I type test example and build it again you'll notice the diamond comes back and if we were to
click this it would run our test.
OK.
Now that's how you how you run an individual test if you want to run all tests.
You can simply click the one on the class.
So if I click that you'll see it will build the project.
It'll pop up in the simulator but it won't run.
It will open it and then basically it'll say it's testing our project and then it quits out.
So as you can tell we have a successful test passed and this test also passed.
However it's a different type of test.
It's a performance test which we can talk about later but it basically said it took zero seconds to
2 to do because there's nothing in it.
So go ahead and actually delete these get rid of this and what we're going to do is we're going to start
by creating an instance of calculation manager but I'm going to use a special keyword.
So go ahead and type var SU t Sutt and then that's going to be of type calculation manager.
OK.
Now if I build this you'll notice the project succeeds but when we get to our tests it says use of undeclared
type calculation manager.
And that's because these two targets are not linked.
Our tests have no way of interacting with our code from our project.
But in order to do that we can go ahead and type at testable OK.
And if we type at testable import we can go ahead and import our project into this test file by typing
the name of our project which is wall Kelk Aroney.
You don't have to name it that that's what I named it.
So if I build and run now you'll see the build succeeds for our project and our calculation manager
shows up properly.
So now we need to go ahead and instantiate calculation manager so that we can use it.
So go ahead and get rid of this comment in the setup function and go ahead and just say oops equals
calculation manager and just create an empty instance of calculation manager.
Something I want you to know though.
Su T is a very very important thing and Su T stands for a system under test and it's a pretty common
way to refer to the system that you're wanting to test and my system is calculation manager so that
is my sut or system under test.
So we have now successfully created a calculation manager.
Now we need to set up our teardown function so that it properly sets our calculation manager to nil
at the end of every test so that we get a fresh instance every time.
So delete that comments and above superdog tear down.
Go ahead and type sut equals nil.
And what that's going to do is it's basically going to make it.
No that's pretty self-explanatory.
So let's begin with our first tests.
What I like to do is I like to open the assistant editor and then open up the actual file that I am
writing test for.
So I'm going to go into my model folder open up my calculation manager here and let's write some tests.
So I basically want to write a test to make sure that when I initialize a calculation manager and give
it values that those values are actually set.
This is a pretty common way to test data models.
So I'm going to go ahead and type phunk test in it.
We're testing the initialization when given values.
OK.
That's the the state or the status like when I give it a value it takes values.
That's the expected result is that it takes our values and they're set properly.
So what we're going to do inside this test is we're going to go ahead and basically set up our own individual
compartmentalize instance of a calculation manager we've already created one appear and we've instantiated
it.
Don't worry that'll be for a separate test.
But what we're going to do is we're going to type let Kelk manager equals calculation manager.
And when I type of parentheses we can instantiate it with a value a value be current operand and value
entry array.
Now that's because this is a struct.
The properties in here automatically create an initializer.
And so let's go ahead and set a value of 10 value B will be 20.
The operand will be how about multiply and the value entery array will just make it an empty array for
now.
So we now have an instance of calculation manager of course it's going to say we're not using it.
And now we're going to go ahead and type ex-city assert equals and we're going to make sure that these
values are actually equal to what we've set.
So go ahead and type ex-city assert equal and type Kelk manager dot value.
And we're setting the other expression to the one that we want to compare it to.
So we're comparing calque manager value to 10.
We're making sure that that value actually was set.
Now if I build this you'll notice that little test Diamond shows up and I click it.
It's going to go ahead and build the project and run our tests so we'll see if our test passes it's
testing and hey look at that test succeeded which is very very cool.
But this is not a complete test.
It's not thorough.
We're only testing one of the values so let's go ahead and let's actually set this up again so that
we can check to see if our you know our calculation is equal.
So go ahead and type ex-city assert equal calque manager value B.
And that should be 20 k let's do this again.
Our current operand when it is not yet an initialized it is optional.
And so I want to make sure that it is not nil so type LCT assert not nil.
And we're going to just verify that Kelk manager dot current operand is not equal to nil.
So if I actually run these tests and by the way you can click this or you can type command you and it'll
run all your test for you.
We're going to go ahead and just make sure that our test here successfully passes.
OK.
Very cool.
So it passes and that means if somehow our initialiser were to change like if I were to just call this
value entry.
OK.
It still will build right it'll still work.
Of course it'll throw some errors in here but our test will fail.
Meaning that something did not work or something broke.
Which is exactly what we want to be testing.
Now there is a much better way to do this.
I have three asserts here but I could very easily convert this into a single assertion.
Now what I'm going to do is I'm going to go ahead and set my calculation manager struck to conform to
the equatable protocol and if I try to build this it'll say hey it does not conform to the protocol
equatable.
So therefore we need to add protocol stubs and so click fix and it's going to create a static function
inside our struct that basically compares one instance of calculation manager to another.
We have L.H. us and our H.S..
So what we're going to do is basically we're going to go ahead and return true.
Well we want to return TRUE saying they're equal.
But if for some reason one value is not equal to another value it's going to return false.
So just follow me here.
We're going to return true saying that one instance of calculation manager is equal to another.
But we need to make sure.
So if LH us dot value a is not equal to another instance.
All right not value a return false.
OK.
So what we're saying hey if our values are not equivalent return false.
OK.
Now we can do that for value b current operand and value A.H. So if LH US DOT value B is not equal to
our H.S. datt value B will return false.
Ok will do it again if LHO s dot current operand is not equal to r h s current operand.
Turn false and I'm sure there is a much more elegant way of doing this.
This just kind of works.
Kind of a quick and dirty method and then we have what value entry right.
Yeah is not equal to our chest.
Value entery array return false.
So what we can do is we can basically get rid of all of these assertions.
We can create Kelk manager one and calc.
Manager to.
And we can basically set them up to be the same.
So I'm going actually just copy this and paste this.
You're probably thinking Hey what is the point of this.
But check it out.
X TC assert equal we can say calc manager 1 and calc manager 2.
We can actually compare two instances of the same class and see if they actually are what we say they
are which is equal.
They're identical.
So let's actually let's make it fail first let's make value a 5.
Let's BuildOn run and our test should fail.
They should not be equal.
So the build succeeded but when the test run it's going to say hey this failed.
And why is that.
Check it out.
The error here that showing up is really not there.
That's a bug.
By the way X-C test is pretty buggy.
The actual assertion failed but the equivalence worked.
We just forgot to build it beforehand.
Sometimes errors get stuck and you'll just see me kind of return down and then the code will re compile
there and it'll work.
So anyway it says that these two instances are not equal.
But if I make them equal and then rerun the test with command you we should see that the test will run.
It will build and the test should pass look at that they passed.
So basically we now can run our test we can check between two instances when we give it values it takes
values they're all properly set.
Now we've tested both.
So there we go.
Very cool stuff.
And you know what we're going to actually head over to the next video now where we're going to continue
testing our calculation manager where we're going to test that our values are initially 0 K and our
calculation manager.
We're going to verify that they're actually zero.
We're going to verify that inserting a value actually changes the value of value.
OK we've got a lot more testing right.
So let's go ahead and let's head over to the next video and let's do that now.