Episode #331

Value Based Testing

Series: Testing iOS Applications

4 minutes
Published on March 23, 2018

This video is only available to subscribers. Get access to this video and 572 others.

In this episode we go over examples of value based testing used for easily testable systems.

This episode uses Swift 4, Xcode 9.2.

- So far we've been

talking about really basic

demo worthy tests that are just asserting

false or true just so we

can see that the mechanics

of test running.

But we want to talk a little

bit about the realistic

examples that we are going

to see and the varying levels

of complexity that our test can encounter.

And so I'm want to start

off with a little bit

of a better example.

Still going to be basic

enough where we can

poke around with it

So I'm going to create a

class called Calculator.

And our calculator's

going to have a method

on it called Add.

And it's going to take

two numbers an X and a Y

and add them together.

And for the sake of the example

I'm just going to return

negative one here.

So for my test case class I

actually want this to be called

CalculatorTests.

And in the most general

case I would prefer to have

every class that I want

to write unit tests for

I'm going to have an

equivalent test case for that.

So we're going to have a calculator test

to test our calculator, we might

have a view controller test

case to test our view

controllers, we might have

something else that's going to test

that particular instance.

Now as things get more

complicated you may want to create

a test case per context

that something is done in.

And that's just going

be up to you basically

in a refactoring step to

break down large test suites

into smaller ones but I

would recommend starting out

with one test case class per

object that you want to test.

Okay so we want to create an

instance of our calculator

and so we might be tempted

to say something like

let calculator equals

calculator like this.

This is problematic because

our test case remember

is going to be created one

time and then all of our tests

are going to be used

on that same instance.

So if we interact with a calculator here

we might inadvertently

be changing the state

of that calculator in this test,

so we don't want to do that.

So instead we want to

declare our types with var

and use the implicitly unwrapped optional.

And instead we're going to

use the set up method here

to set up a new instance of our

calculator every single time

through our test run.

Like that so this is a

good habit to get into.

Don't reuse anything between tests.

Okay so we've got our

calculator here I want to

make a descriptive method

test adding two numbers.

And here I want to take our

calculator, I want to add

two numbers together so I'm

going to say let the result be

calculator.add and let's

say we add four and eight.

And then I've got my expected

value which I believe

is going to be 12.

And so now I can run my

assertion XETAssertEqual

my expression one is going

to be the result that we got

remember the results or the actual value.

And then the expected value second.

So now that we have that.

We should see that this

test is actually failing.

Actually I changed the name of

this test so I need to change

the way its run down here.

We should see this test

fail because negative one

is not equal to 12.

So adding is not working

out correctly here.

And we can fix this test by changing this

to return X plus Y.

And now our tests are passing.

So this is the quick feedback that I like

about using Playgrounds to run tests

because I didn't have to type,

I didn't have to do anything

to make the test run I just

typed the code and it ran it.

Okay, so this is what I like

to call value based testing

we give it some static inputs

and we get back a result.

This is the easiest possible

type of test we could write.

This is called value based

testing because we're only

testing with values.

Our calculator doesn't have

to reach out to the internet

to pull down stock quotes or anything.

We don't need to save

anything to a data base.

There's no side effects that happens here.

It's a pure function, it's

inputs and it's outputs.

And these things are desirable.

If you can design your

software entirely with inputs

and outputs that have no side effects

it becomes really, really easy to test.

Unfortunately the real

world isn't quite so easy

to work with and so we're

going to end up with tests

that are more complicated than this.

But I think that as we're

building our applications

it's worth striving for tests

that or application code

that is really geared

towards inputs and outputs.

Try to build code that

doesn't have side effects.

If we have an add method

that writes to disk

this is probably a bad

responsibility for this method.

So in this way the desire to

have an easily testable system

can also help in designing

our software in a way

that is testable which

happens to be inherently good

object oriented design anyway.

So that's basically what

we want to strive for

is value based testing.