TestUnit - Writing Test Code In Ruby (1/3)
Tags: beginners, ruby, testing, tutorial
Published: 2019-06-13 02:53:41

---
title: TestUnit - Writing Test Code In Ruby (1/3)
published: true
description: 
series: ruby-tests
tags: beginners, ruby, testing, tutorial
cover_image: https://thepracticaldev.s3.amazonaws.com/i/hvn03gvwa404n6wh01vu.png
---

**Mini Series**
* [TestUnit - Writing Test Code In Ruby (1/3)](https://dev.to/exampro/testunit-writing-test-code-in-ruby-part-1-of-3-44m2)
* [MiniTest - Writing Test Code In Ruby (2/3)](https://dev.to/exampro/minitest-writing-test-code-in-ruby-part-2-of-3-4306)
* [RSpec - Writing Test Code In Ruby (3/3)](https://dev.to/exampro/rspec-writing-test-code-in-ruby-part-3-of-3-32np)


**Prelude to Learning**
I'm training my juniors on how to write test code since we need to improve our code coverage in ExamPro. I had quickly put together three guides last Sunday on TestUnit, MiniTest and RSpec. Why all three? I believe that learning by variation results in complete knowledge.

I figured I should publish these three articles on DEV.to articles "as is" otherwise I'll forget about them, they'll end up in my "Dump" folder, never to been seen again.

**p.s.** I had written challenges to each of these guides. I don't know if people want them. Show me enough reactions, comment below if you want them, and I'll find the time to publish them if there's interest.

## TestUnit
TestUnit is a standard ruby library.
Standard ruby libraries mean you do not have to install a gem because it's already included with the language.

The simplest example of using TestUnit is as follows.

```ruby
require "test/unit/assertions"
include Test::Unit::Assertions

hello = 'world'

assert_equal 'world', hello, "hello function should return 'world'"
```

## Assertion Functions

`assert_equal` is one of many assertion functions.
Assertion functions are part of all of the testing libraries to assert whether
something will pass or fail. The assertion is your "test".

Here is a list of all assertion functions which are part of TestUnit.
In practicality, you will be using a handful of these assertion functions.

```
assert
assert_block
assert_boolean
assert_compare
assert_const_defined
assert_empty
assert_equal
assert_fail_assertion
assert_false
assert_in_delta
assert_in_epsilon
assert_include
assert_instance_of
assert_kind_of
assert_match
assert_nil
assert_no_match
assert_not_const_defined
assert_not_empty
assert_not_equal
assert_not_in_delta
assert_not_in_epsilon
assert_not_include
assert_not_match
assert_not_nil
assert_not_predicate
assert_not_respond_to
assert_not_same
assert_not_send
assert_nothing_raised
assert_nothing_thrown
assert_operator
assert_path_exist
assert_path_not_exist
assert_predicate
assert_raise
assert_raise_kind_of
assert_raise_message
assert_raises
assert_respond_to
assert_same
assert_send
assert_throw
assert_throws
assert_true
build_message
flunk
```

## Assert and Flunk

The most basic assertion functions are `assert` and `flunk`.

A function signature defines the inputs and outputs of a function.
You can find functions signatures in the technical documentation for
your language and libraries. Let's look at the function signature for
'assert and `flunk` which are defined on [RubyDocs](https://www.rubydoc.info/gems/test-unit/2.3.0/Test/Unit/Assertions#assert-instance_method).


### Assert

This is the function signature for `assert`

```
#assert(boolean, message = nil) ⇒ Object
```

Here we can see `assert` takes two parameters for input:
1. boolean - which is required
1. message - which is optional

And it outputs an `Object`.

This is how we could use this function

```ruby
# simple.rb
require "test/unit/assertions"
include Test::Unit::Assertions

x = true

assert x, "x should pass"
```

### Flunk

This is the function signature for `flunk`


```
#flunk(message = "Flunked") ⇒ Object
```

Here we can see `flunk` takes one parameter for input:
1. message - which defaults to "Flunked" if no value supplied

And it outputs an `Object`.


This is how we could use this function

```ruby
# flunk.rb
require "test/unit/assertions"
include Test::Unit::Assertions

flunk "throw a failure message"
```

The purpose of `flunk` is when you a test that always fails.
You may not find practical utility in `flunk`

## How to Properly Write tests with TestUnit

The examples above were the fewest amounts of lines to use TestUnit but this is not the correct way.
The correct way is to create a separate file.
This new test file will require the code we wish to test and we will need to create to TestCase class to then write test functions.

### Hello World TestCase Example

We'll create a simple class within its own file called `hello.rb`.
This class will have a class method called `self.hello` which will return a string.

```ruby
# hello.rb
class Hello
  def self.world
    'world2'
  end
end
```

We will create a new file called `hello_test.rb`
Notice that we gave the file name the exact name and then appended `_test` to the end it.
You will find later when you have more test files you will want to stick to this convention because of automation tools.


```ruby
# hello_test.rb
require "test/unit"
require_relative './hello'

class HelloTest < Test::Unit::TestCase
  def test_world
    assert_equal 'world', Hello.world, "Hello.world should return a string called 'world'"
  end

  def test_flunk
    flunk "You shall not pass"
  end
end
```

The class we defined is not a normal class but is a **Domain Specific Langauge (DSL)**.
A DSL is when you change the behaviour of your code to act as a language within a language.
The ruby language is a very malleable language and as a result, it easy to write DSLs.
The ruby community frequently says code is "magic" when referring to DSLs.
The rules of how a DSL is not always clear which can lead to common confusion.

The `HelloTest` class extends `Test::Unit::TestCase` which is where the "magic" that turns this class into a DSL.
When this file is executed eg.

```
ruby hello_test.rb
```

It will output the results of the tests.
It will execute each instance function in the `HelloTest` class that begins with `test_`

1. test_world
2. test_flunk

It the instance function is not named with `test_` then it will not run.
This is part of the rules of this DSL.

### Thoughts on TestUnit

`TestUnit` is not the only testing frameworks in ruby since we also have `MiniTest` and `Rspec`.
These other testing frameworks have different tradeoffs but are similar in functionality.

`TestUnit` is the old and simple test framework.

In the upcoming lectures, we are going to explore both `MiniTest` and `Rspec` and
learn the trade-offs.

All frameworks are used, it is hard to say which is most commonly used
and it comes down to team preference.

## Code

{% gist https://gist.github.com/omenking/a6d056d4294168bb8628553d3bd79f18 %}

{% gist https://gist.github.com/omenking/302ba7e0292cf4bef50287af052a19cb %}

{% gist https://gist.github.com/omenking/3dfd6707f3ac8cc06fdd4f40739d03f7 %}

{% gist https://gist.github.com/omenking/037e1d6732fc8f0db7ea5a93d3c26f91 %}


## References
https://stackoverflow.com/questions/12317921/why-undefined-method-assert-equal-is-thrown-even-after-requiring-test-unit
https://apidock.com/ruby/Test/Unit/Assertions
https://www.rubydoc.info/gems/test-unit/2.3.0/Test/Unit/Assertions
https://stackoverflow.com/questions/6515333/how-do-i-execute-a-single-test-using-ruby-test-unit
https://mattbrictson.com/minitest-and-rails