MiniTest - Writing Test Code In Ruby (2/3)
Tags: beginners, ruby, testing, tutorial
Published: 2019-06-13 02:59:29

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

**p.s.** This is a series of articles and each article builds off another. I suggest starting at [Part 1](https://dev.to/exampro/testunit-writing-test-code-in-ruby-part-1-of-3-44m2).

**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)

## MiniTest

MiniTest is similar to UnitTest in that is has assertion functions
in the style of xUnit/TDD. This style we are referring to is the fact that
our assertion functions all start with `assert_`

MiniTest has more built into tools that make it easier to manage and run
tests.

MiniTest is also capable of spec/BDD style tests which will talk about later.
Here are the various promises that MiniTest provides out of the box:

```
minitest/autorun - the easy and explicit way to run all your tests.
minitest/test - a very fast, simple, and clean test system.
minitest/spec - a very fast, simple, and clean spec system.
minitest/mock - a simple and clean mock/stub system.
minitest/benchmark - an awesome way to assert your algorithm's performance.
minitest/pride - show your pride in testing!
```


MiniTest is not a standard library.
To install MiniTest we will need to install the gem.
Gem is what ruby calls a library.
Gems are commonly managed using bundler which is a package manager.
We are going to be using bundler in all future lectures.


## Setting Up Bundler and Installing MiniTest

### Install Bundler
To start using bundler we must install the bundler gem via rubygems.

```
gem install bundler
```

### Create Gemfile
Once bundler is installed we can now create a `Gemfile`.
A `Gemfile` defines all the gems our code will need to depend on.
We can specify exact gem versions and bundler call automate the
installation and update of these gems.


We will proceed to create our `Gemfile`

```ruby
# Gemfile
source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

gem 'minitest'
```

In our `Gemfile` we have to specify where we want to get our gems.
So here we say we want to download our gems from `rubygems.org`
```
source 'https://rubygems.org'
```

In order to pull in gems from github we need to add a hack.
In the past this hack was not required but is now in the norm for all ruby projects.

```ruby
git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end
```

Then we can list the gems we want to install, So here is where we
include `minitest`

```ruby
gem 'minitest'
```

### Bundle Install

To install the `minitest` gem via bundler we need to run in terminal:

```
bundle install
```

Bundler will proceed to install or update gems and produce a
`Gemfile.lock` which is known as a lockfile.

### Lockfile

The lockfile is to lock down specific gem versions in order to ensure
others who want to run our code don't run into errors caused by using
the wrong versions of gems.

You can not manually modify the lockfile.


## Turning our UnitTest into MiniTest

We are going to test our `Hello` class from the last lecture.
```ruby
# hello.rb
class Hello
  def self.world
    'world2'
  end
end
```

We previously wrote a `HelloTest` class using `UnitTest`.
Let us convert it to use `MiniTest` and compare the differences.

```ruby
require 'minitest/autorun'
require_relative './hello'

class HelloTest < Minitest::Test
  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
```

We only changed two things the require:
```
require 'minitest/autorun'
```

and the class which we are extending.

```
class HelloTest < Minitest::Test
```

`MiniTest` is very close in DSL syntax and assertion function naming to `UnitTest`.
This is no coincidence as it was intended to help developers to port their `UnitTest` code to `MiniTest`


## Running MiniTest

Since we are using bundler to managed our gems when we run our test file
we need it to perform it in the context of bundler. We can do this by
using `bundle exec`. This is how we would run our test:

```
bundle exec ruby hello_test.rb
```

## Assertion Functions

We looked at the `UnitTest` assertion functions previously. Lets see how they compare to `MiniTest`:

```
assert
assert_empty
assert_equal
assert_in_delta
assert_in_epsilon
assert_includes
assert_instance_of
assert_kind_of
assert_match
assert_mock
assert_nil
assert_operator
assert_output
assert_predicate
assert_raises
assert_respond_to
assert_same
assert_send
assert_silent
assert_throws
capture_io
capture_subprocess_io
diff
exception_details
flunk
message
mu_pp
mu_pp_for_diff
pass
refute
refute_empty
refute_equal
refute_in_delta
refute_in_epsilon
refute_includes
refute_instance_of
refute_kind_of
refute_match
refute_nil
refute_operator
refute_predicate
refute_respond_to
refute_same
skip
skipped?
```

Many of the same assertion functions exist and there are new functions that did not exist prior.
`MiniTest` is not 1-to-1 the same as `UnitTest`.

## So Many Extensions

MiniTest has hundred of extensions in the form of gems.
This is one advantage over `UnitTest` since you can customize your testing framework to your needs.
Here are a few examples:


```
minitest-line    - Run test at line number.
minitest-logger  - Define assert_log and enable minitest to test log messages. Supports Logger and Log4r::Logger.
minitest-osx     - Reporter for the Mac OS X notification center.
minitest-profile - List the 10 slowest tests in your suite.
minispec-rails   - Minimal support to use Spec style in Rails 5+.
```

## MiniTest's alternative spec/BDD syntax

So far we have been using Test Drive Development (TDD) which is a
methodology for writing test code. There is another newer way of writing
tests (which are called) using Behaviour Driven Developement (BDD).

The goal of BDD is to define tests that are both more human readable and
written in such a way that it's more likely to cover all edge cases.


Let us convert our TDD MiniTest over to BDD.

```
# hello_spec.rb
require 'minitest/autorun'
require_relative './hello'

describe Hello do
  describe "#world" do
    it "should return world" do
      Hello.world.must_equal 'world'
    end
  end
end
```

BBD uses a heavy DSL using ruby blocks `function value do`.
The assertion functions are both used and named differently.

`assert_equal` has now become `must_equal`
The assertion function now uses a syntax known as chaining.
These changes are intended to make the test more human readable.

Let us compare:

```ruby
# TDD "test"
assert_equal 'world', Hello.world, "Hello.world should return a string called 'world'"

# BDD "spec"
it "should return world" do
  Hello.world.must_equal 'world'
end
```

## We can run this spec file just as we did our test:

```
bundle exec ruby hello_spec.rb
```

## Thoughts on MiniTest

`MiniTest` can handle both TDD and BDD syntax.
It comes with a bunch of testing tools to make automation easy
There are several extensions to customize `MiniTest` to your needs.
It is fairly easy to port `TestUnit` to `MiniTest`.
`MiniTest` does have to be installed via bundler.

In the next lecture, we are going to look at RSpec which is solely a BDD tool.

## Code

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

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

{% gist https://gist.github.com/omenking/18d2cfd72726af763d6b38b028d1128f %}

{% gist https://gist.github.com/omenking/7b44d60633650f37a357b9945627b8a9 %}


## References
https://mattbrictson.com/minitest-and-rails
https://github.com/seattlerb/minitest
http://docs.seattlerb.org/minitest/Minitest/Assertions.html