In this quick post, I hope to explain with some common math abstraction how I perceive Unit testing and Integration testing.
Disclaimer: This is post is only meant to provide the notions behind testing, is not meant to be an in-depth testing explanation 😛
Okay, you must be asking yourself, why? I mean, not all coding is created equal, and let's be honest - you don't really need to understand math to code. However, I do believe that - and this comes from someone who flunked calculus and algebra numerous times in college - math is fascinating and a great tool to explain concepts in a simple manner.
A function is a process or a relation that associates each element x of a set X, the domain of the function, to a single element y of another set Y
I can't find a better definition than to look at it as a black box. A function is a black box that, when given a value, will return something else.
Okay, cool - that's as much math as you need to know for what's next!
So here's the thing, we want to test functions. We want to make sure they return the correct value each time they're called. We have this first function
f(x) which returns the given number
x plus one. Then, we have
g(x, y) which does a bit more, it returns the sum of
x plus the result of
What's going on here? we have one function
f(x) that we can test by itself as it has no dependency on another function. This is what we can consider something that can be tested as a unit.
Then, there's another function
g(x, y) which implements
f(x). It needs
f(x) to produce a value. It is directly dependant and therefore needs this other function to live. Nothing like a math love story. 💙
So for both functions, we will end up having something like this:
Now that we have coded our functions, we want to test this first function
f(x) and make sure that it returns the correct value for
x = 1
We also want to test that
g(x, y) returns a correct value for
x = 2 ; y = 1
I will be using Jest for these examples, if you still don't know about Jest, give it a shot, it's an amazing testing framework for js!
So for the following test suite We will be expecting that when we call these functions with the params described above, they should actually return what we expect.
One thing to highlight here is that by testing
g(x, y) we are implicitly testing
Can we test
g(x, y) as a unit? Up until now we now that
g(x, y) depends on
f(x), so its result will be bound to the result of
...or will it? 🤔
Mock is a very interesting concept when it comes to testing. For some controversial, for some a helpful tool. I am not here to discuss this, but rather give you the notion of what mocking is, and how we could use it to test
g(x, y) without any dependencies.
With mocking you can override, substitute, manage things that should be out of your control. In this example, because of how
g(x, y) is built, we should not be able to look inside our
black box and replace
f(x) with something else.
This is where mocking comes in. In an uncontrolled environment, it allows you to open up the
black box and substitute parts of how the system behaves to your will.
It would be the equivalent to doing something like this:
Now, because we have tampered with
g(x, y)'s black box, it will produce a new output.
Compare that to the example above, in which we don't have access to the black box
These are not equal scenarios, hence why researching how to mock properly is something worth investing some time in!
So then - can we test
g(x, y) in isolation? as a unit?
Yes! - Jest offers a lot of functionality for mocking
⚠️ Should you test
g(x, y) in isolation?
It depends - are you testing edge cases? is
f(x) an external dependency out of your control? There are a lot of things to keep in mind before mocking.
So that's it! A basic introduction to testing explained with math functions.
Hope you liked this post - keep hacking! 🔥