Unit testing is simple
Tags: testing
Published: 2017-05-04 06:56:56

---
title: Unit testing is simple
published: true
description: You don't even need a framework for unit testing. You don't even need to write the test in a separate file or class.
tags: testing
---

_https://www.scalawilliam.com/unit-testing-is-simple/_

Is unit testing difficult?

No, it is not. You don't even need a testing framework for it.
You don't even need to write the test in a separate file or class.

You just need to [exit with code 1](http://tldp.org/LDP/abs/html/exitcodes.html). This is enough to fail a Jenkins build and a Makefile!

Why is a unit test useful?
- Prevent regressions when you change the code.
- Document expected input and output as code.
- Replace error-prone [println-driven development with test-driven development](http://codebetter.com/jeremymiller/2006/06/01/tdd-and-debugging/).

> **What do you test?** when the logic is "complex enough" I know it could be broken 6 months down the line, due to "that one small change" - or that I'd spend time building it with print statements. [Example from my own code](https://github.com/ActionFPS/dashboard/blob/e757931de22d82edd20e4ef5ad3b2df56d433a16/test_build.py#L82).

Here, I'll show you the most basic way to unit testing with four languages: Bash, Python, Node.js, Scala, just to prove the point. 

These examples are for a very basic piece of code and are intentionally minimalistic, to demonstrate that you needn't use a test framework to get started with - though one will be very necessary when you scale your application.

## Bash
Here's a bash script `inc.sh` with a basic assertion and some main code:

```bash
#!/bin/bash

increment() {
    echo $(("$1"+1))
}

# If this assertion fails, the whole thing quits 
[ 3 -eq $(increment 2) ] || exit 1

# Increment a stream of numbers
while read n; do
    increment $n;
done
```

If we run:
```
$ seq 1 5 | bash inc.sh
2
3
4
5
6
$ echo $?
0
```

Exit code is 0. But if we broke the function, and put 2 instead of 1, we get:
```
$ seq 1 5 | bash inc.sh
$ echo $?
1
```

## Python

This is easy to achieve in any language really. [Python assertions](https://docs.python.org/2/reference/simple_stmts.html#the-assert-statement):

Broken test in file `inc.py`:
```python
def increment(n):
  return n + 2

assert increment(2) == 3
```

```
$ python inc.py
Traceback (most recent call last):
  File "inc.py", line 4, in <module>
    assert increment(2) == 3
AssertionError
$ echo $?
1
```

## Node.js

Comes with [assertions built in](https://nodejs.org/api/assert.html#assert_assert_equal_actual_expected_message).

Broken test in file `inc.js`:
```js
const assert = require('assert');

function increment(n) {
  return n + 2;
}

assert.equal(2, increment(1));
```

```
$ node inc.js

assert.js:81
  throw new assert.AssertionError({
  ^
AssertionError: 2 == 3

...
$ echo $?
1
```

## [Scala](http://scala-lang.org/)

Comes with assert.

```scala
def inc(n: Int) = n + 2
assert(inc(1) == 2)
```

```
$ scala inc.scala
java.lang.AssertionError: assertion failed
$ echo $?
1
```

# Why is this important?

You can get started light with several assertions and work your way up to proper test suites.

# So what are test frameworks for?

To make testing more organised. You get:
- Organisation
- Detailed error messages
- Detailed test reports
- Neat assertions and human readable language (see [ScalaTest](http://www.scalatest.org/))
- Incremental/TDD type of development

# Conclusion

Now you have no excuse for not writing at least a few tests in your code.