Press "Enter" to skip to content

Unit testing in JavaScript Part 2 – Your first tests


good Monday morning today we are

continuing our journey on unit testing

in JavaScript in the last episode that

you can find in the episode description

we explored the why behind unit testing

and the why is to keep the complexity of

our code from overwhelming us today

though we are going to focus a little

bit more on what unit testing is and how

it helps with managing complexity

I am empty J’s and you are watching fun

function

[Music]

last week we wrote some code order total

the function order total order total was

a function that took a piece of data an

order and grabbed all the items in the

order and summarized them for us in an

in an order total today we’re going to

write that same function but we are

instead going to do it with a test first

approach I also want to state for the

record that today I am enormously tired

it’s just one of those days where the

caffeine doesn’t work let’s do some

coding and see if we can get some

energies today all right here on first

here on line one we call order total

with an order any recognize this sample

data from the last last episode and here

we check if the the the order total

returned from orders all isn’t 808 we

throw an error check fail by happy part

here I mean they’re basically the case

the standard case where everything goes

well there’s no weird edge cases or

anything it’s just the main main thing

that the function is supposed to do

alright so there’s no actual code here

or total here it does not exist yet we

wrote the test first can i us be the

devil’s advocate and ask why we are

doing it this way why are we writing the

test first instead of writing the code

first and then adding a test later

well the biggest benefit for with test

first for me is that it helps ensure

that I actually write the

tests at all I find that if I start

adding tests after I’ve written the code

when I try to do that I tend to slack on

that and the reason why I slack on that

is that it’s just harder to write tests

afterwards than before and the reason

why it’s harder is that it’s hard to

figure out what tests what tests right

okay can you can give an example okay

maybe can you perhaps can give an

example of that okay let’s have a look

at the code from the last episode how

how do I increase the font size zooming

zoom fantastic okay so these the this is

only eight lines of code but even just

at eight lines we already have multiple

use cases in the code and now since we

didn’t add the tests while we were

writing them I have to have two now

after the fact analyze the code and like

archaeology those out okay but is that

really all that hard no it’s not it’s

not rocket surgery by any means but it

is busy work that we can avoid adding

tests after the fact to me is like

adding an extra unnecessary archaeology

step where we try to extract things from

our own code if I try to make an analogy

and it’s an analogy so it’s not perfect

but it feels a little bit like if let’s

say that we were a chef and we we were

inventing a new recipe we were just

playing around and adding things to to

the soup and eventually like the soup

turned out really well and when we when

it then it’s time to write the recipe

down so that non cooks could do it and

as we didn’t really keep tabs on what

ingredients we put into the soup we now

have to like

hmmm look in the soup and like

after-the-fact try to figure out which

ingredients we put in there like poke

around in it

and that would sort of work we might

miss an ingredient there and might take

a little bit more time but it would work

but to me it seems like it would have

been more sensible to make notes of what

we added to the soup as we did it that

to me seems more effective and reliable

alright fair enough

let’s go back to the original code okay

we are doing test first today which

means that we only write code when there

exists a test that requires that code to

exist mmm I think I’m lisping a bit

today so in this case here we see that

order total does not exist that’s a very

obvious problem one part about unit

testing is that you constantly try to

put yourself in these situations where

the next step becomes obvious all right

function order total alright now it

fails for another reason

that’s good progress again unit testing

is about making these small very

incremental steps of progress towards a

goal we create this very nice feedback

loop for our work it’s almost a little

bit like like a game where you like you

when you hop on an enemy like that gives

you a satisfying group when you like the

Goomba goes away hey dice

and now like getting to a new level in a

video game we have a new challenge which

is that this check here this fails the

happy path a check fails because this is

not one eight oh eight no because this

is an empty function is returning

undefined so again let’s remember that

when we are doing tests first

we try to always only write code that is

required by a test to pass so

first impulse here might be to start

writing writing and reduce like order

items reduce but that’s not actually

what the tests requires if we are being

really strict about the rule of only

writing code that tests require we could

do return rate and test succeeds

what the what is this this

feels so unintuitive to me yes

this is if you do test first by the book

and really take it to its logical

conclusion this is what you what you end

up with like this is a very common

situation weird you are weird all right

so you really need to explain this to me

what okay we have the test passing now

but the code is obviously wrong how do

we how do we proceed from here all right

so there are three different approaches

that you can take when you are writing a

test first you can use obvious

implementation fake it till you make it

or triangulation and these techniques

they go from Orthodox to more chill

let’s talk about triangulation first

because that is the most conservative

way of doing test-driven development

okay triangulation what does that mean

exactly is that it is triangulation that

thing you do with points on a map and

you figure out where something is based

on three points yeah exactly that’s

where the name comes from and it’s kind

of similar in in unit testing because

often you find yourself in this

situation where one test is not quite

enough to drive the implementation

so let’s actually write another test I’m

just gonna copy paste this and I’m going

to do like drag on caller and I’m gonna

set that price to 20

we’re gonna do dragon shoe toy and I’m

gonna set that price to 4G perhaps and

I’m going to name this case happy path –

example1 example2 and this is supposed

to be 60 I’m doing the math in my head

and now we have this second test here

that is failing which will cause us to

actually have to write some code so

are you getting this with the whole

red-green cycle going on in in test

driven in test first that you oh it’s

red and you get sad and then you write

some code and then you get screen and

you go happy again and then red and you

go sad and yeah they’re getting it also

I would like to State for the record

that this feels really weird

uh I think I get it though I can see

value where the triangulation yeah I I

think this feels safe it feels like it’s

because it feels like it’s hard to make

mistakes with this and it also has this

quality of making it obvious what to do

exactly get to green at all costs just

focus on what code you need to write in

order to make the test pass and then

look at the code and try to figure out

what it is that we need to add and then

add a test for that and then the loop

continues again red green red green red

green however I would like to stress

that triangulation is not the only way

of doing tests first we could also have

gone immediately for the obvious

implementation once we had the first

test and just written written this

reduce function out because it is it’s

still kind of obvious that that is what

we are going for we could also take in a

middle road which is fake it till you

make it and that is kind of yeah that’s

in between so what we would have done

there is that we would have we would

still have first gotten to green as fast

as possible by just writing the

hard-coded value in 808 but then we

would have immediately replaced it with

the with the actual implementation so

you kind of it’s it’s kind of in-between

all of these are absolutely tests first

techniques

but they are different different

different in their Orthodox Ness if you

are a beginner it might be good to stick

with triangulation for a little while

because it’s the the simplest one it’s

the one that is most pure to test first

and it will be the technique that most

gives you a feel for test tests first as

something to integrate in your workflow

and then once you get the hang of it you

can start like dumping into these more

relaxed approaches sometimes okay now

that the initial weirdness feel has died

down I think a kind of like

triangulation though emotionally

conceptually I can see it being a bit

slow to work with well a bit slower a

bit more calmly paced but it does have

this huge benefit of giving me an

obvious way forward all the time that

seems very calming to me I can see

myself jumping between these actually

but falling back to triangulation on

days where I have more complicated

problems or perhaps some days where I’m

you know feeling a little bit lazy or

yes just having a down day and I have a

hard time thinking then triangulation

could kind of keep me from doing these

long thought jumps in my head and just

keep me focused on the red green red

green red green loop alright let’s let’s

add another test let’s let’s add our

quantity support

[Music]

all right so this test that we just

wrote the quantity quantity test now

works because we added code for that

however these tests here they have

failed and this have failed as well we

just don’t see it because this flows the

error first but this this would also

fail because these things have no

quantity in them and our code now expect

this we have we made a breaking change

okay yeah I get why does this we have we

have changed the API of our code and we

have tests in place to verify that API

which means that we now have to change

all our tests I feel like this is giving

us extra work fixing these tests and

this feels like work that wouldn’t exist

if we didn’t have the unit testing place

ah it kind of saw the right but you’re

also kind of sort of wrong you need to

have a little bit of imagination in this

particular case this is mostly as extra

work but that is true only because we

don’t yet have any external code that is

making use of our order total our test

did break because we actually made a

change to the a breaking change to the

API of already total if order total had

been in like some library that was used

by thousands of users you couldn’t make

a change like this without doing like a

major version bump and announcing it to

all the users because they might have

code that relies on that the API follows

a certain contract and that is what unit

tests verify so if or the total had been

in use for a while before we added the

quantity support then this the unit test

breakage here would actually have

highlighted a very real problem you know

what let’s I was about

to change these these two code example

these two tests here and just add

quantity one to them but I think that we

should pretend that code in in the

system is consuming this and perhaps

even third party code in in other

libraries because it it’s not

unreasonable to think that something

like order total might be very useful

for many system and that you might want

to change this logic or its share this

logic sorry so let’s actually make sure

that both cases work so I’m gonna warm

up my quantity 0 there does that work I

think I have to I put that in parents oh

no no it can’t be Syrians to be 1 and

yeah this works now observing this code

it feels like we are baking in a bit

much in the happy path examples now here

it feels like these are not actually

testing the happy path now they are

testing the happy path and lack of lack

or quantity or the lack of quantity case

so what I’m actually gonna do is that

I’m going to create a dedicated happy

path case

now that we have this check for no

quantity specified we can safely extend

these happy path examples to be actually

so as you see here we we keep the tests

very small and focused on one thing only

so you see here that this test for

instance there’s a lot of things that

this test does not test it doesn’t test

it only has one item so it’s not

concerned with with many items and it

also tests only the only the quantity

case like having no quantity case like

the implied quantity case that is that

is only con this test is only concerned

with that the happy part test it tests

it happens to test a little bit more but

these tests or if I use the happy part

test mainly to get me going to get

started and a happy path it’s okay that

tests a little bit more than one thing

but overall unit testing it refers to

like for the total as a unit that we can

test in isolation that’s that’s one way

of interpreting the unit word in unit

testing but it’s also important that

each test is a unit that it doesn’t like

test

hagh tons of code in hoc tones of cases

in in one test that becomes really

really hard to deal with

once multiple things start breaking it’s

a much nicer to to have each

each unit tests be it’ll be a unit in

this episode I also focused a lot on the

benefit of habit that unit tests have on

or test-driven development or test first

has on dealing with complexity but I

want to make a segue here and also note

that unit test also works as a

communication channel a really good

communication channel to your future

selves or your colleague yeah because

these tests basically double as very

specific and very nice executable

documentation for your code normal

documentation with you know examples and

stuff that is also very nice but unit

has a very like a very good supplement

to normal documentation because they get

really into the nitty-gritty of how

exactly a function works okay so uh what

about you know test runners I’ve heard

about mocha and jest and Jasmine and

whatever like we have not used them here

we have just done these very like very

hand coded handcrafted checks yeah I

have actually avoided introducing a test

runner at this stage because I I want

you as a viewer to learn as few things

as possible at the same time if we

introduce a test runner you would have

to learn a test runner while also

learning the basic principles of test

first and unit testing and it just feels

like we can introduce things

sequentially but test runners is what we

are going to talk about in the next

episode which brings me to that you have

just watched an episode on function I

really ever

Oh 800 GMT if you are watching from the

future you can check out next week’s

salute otherwise subscribe here so that

you don’t miss it

if you are forgetful you can also turn

on notifications

I am MJ until next Monday morning thank you

Please follow and like us: