Ruby
We use minitest as a testing framework for Ruby coding exercises.

Hello, World!

Before we go into details, let's see how you can use minitest to test the most basic Ruby task: writing a function that returns "Hello, World!".
This is what a student might write (hello.rb):
1
def hello_message
2
"Hello, World!"
3
end
Copied!
And this is an example of what you could write to evaluate the student's code:
1
require "minitest/autorun"
2
require "./hello"
3
4
class Evaluate < Minitest::Test
5
def test_hello_message
6
assert_equal "Hello, World!",
7
hello_message,
8
"Your function should return: Hello, World!"
9
end
10
end
Copied!
Let's examine the above evaluation code.
We first need to require the minitest framework and the user file(s).

Minitest::Test

Then we need to define a suite of unit tests as a class that inherits from Minitest::Test.
This groups together multiple unit tests and allows implementing common functionality that you want executed before and after each test, via the setup() and teardown() methods respectively.
Unit tests can be implemented as methods inside this class that start with test_. These are the only functions that will be executed when running the evaluation code.
1
class Evaluate < Minitest::Test
2
def setup
3
# This code will be executed before every unit test.
4
end
5
6
def teardown
7
# This code will be executed after every unit test.
8
end
9
10
def test_something
11
# This is a unit test.
12
end
13
14
def test_sometings_else
15
# This is another unit test.
16
end
17
end
Copied!

Assertions

Assertions are the statements that actually verify that the student's code behaves as expected. The most common pattern is to call student's methods and assert that their return value is the one that you expect. If it is not, then the test will fail and you have the opportunity to provide a custom message to the student for each failed assertion, so that she can improve.
These are the most common ones:
1
assert(boolean_value, msg = nil)
2
assert_equal(expected_value, actual_value, msg = nil)
Copied!
The assertion from the Hello World example could be rewritten as:
1
assert "Hello, World!" == hello_message,
2
"Your function should return: Hello, World!"
Copied!
If any of the assertions in your unit tests fail, the test is marked as failed and feedback (the msg parameter) is given to the student.

Standard output

In the previous example we had the students return Hello, World!, but actually a more common task is to have them print the same string to the standard output.
1
def say_hello
2
puts "Hello, World!"
3
end
Copied!
How do we test this specific function?
1
require "minitest/autorun"
2
require "./hello"
3
4
class Evaluate < Minitest::Test
5
def test_hello_message
6
out, err = capture_io do
7
say_hello
8
end
9
10
assert_equal "Hello, World!\n", out, "Your function should return: Hello, World!"
11
end
12
end
Copied!
Minitest provides the capture_io method which captures and returns standard output and standard error for all the statements that are executed within the method's block.

Technical specs

    Ruby >= 2.3.1
    Minitest >= 5.9.0

Example 1: FizzBuzz

Given:
    An integer number n
Your task is to:
    Write a function that returns an array with the numbers from 1 to n with the following restrictions:
      for multiples of 3 store "Fizz" instead of the number
      for multiples of 5 store "Buzz" instead of the number
      for numbers which are multiples of both 3 and 5 store "FizzBuzz"
Example:
1
fizzbuzz(15) == [
2
1, 2, "Fizz", 4, "Buzz",
3
"Fizz", 7, 8, "Fizz", "Buzz",
4
11, "Fizz", 13, 14, "FizzBuzz"
5
]
Copied!
Here's how a student might solve the problem:
1
def fizzbuzz(n)
2
result = []
3
4
(1..n).each do |i|
5
if i % 15 == 0
6
result.push "FizzBuzz"
7
elsif i % 3 == 0
8
result.push "Fizz"
9
elsif i % 5 == 0
10
result.push "Buzz"
11
else
12
result.push i
13
end
14
end
15
16
result
17
end
Copied!
Here's how you might test the student's solution:
1
require "minitest/autorun"
2
require "./fizzbuzz"
3
4
class Evaluate < Minitest::Test
5
def test_fizzbuzz_simple
6
assert_equal [1], fizzbuzz(1), "fizzbuzz(1) should return [1]"
7
end
8
9
def test_fizzbuzz
10
result = fizzbuzz(15)
11
12
assert result.kind_of?(Array), "Your function should return an array"
13
14
expected = [
15
1, 2, "Fizz", 4, "Buzz",
16
"Fizz", 7, 8, "Fizz", "Buzz",
17
11, "Fizz", 13, 14, "FizzBuzz"
18
]
19
20
assert_equal expected.length,
21
result.length,
22
"Your function should return #{expected.length} objects"
23
24
result.each_with_index do |obj, idx|
25
assert_equal expected[idx],
26
obj,
27
"Your function should map #{idx + 1} to #{expected[idx]} instead of #{obj}"
28
end
29
end
30
end
Copied!

Example 2: Title Case

Given:
    A sentence with words separated by spaces
Your task is to:
    Write a function that returns a copy of this sentence where all the words:
      start with a capital letter
      the rest of the letters are lower case
Note:
    Your function should not modify the sentence given as argument.
Example:
1
normalize("This is SO MUCH FUN! ") == "This Is So Much Fun! "
Copied!
Here's how a student might solve the problem:
1
def normalize(sentence)
2
copy = sentence.dup
3
idx = 0
4
5
while idx < copy.length
6
idx = skip_whitespace copy, idx
7
idx = normalize_word! copy, idx
8
end
9
10
copy
11
end
12
13
def skip_whitespace(sentence, idx)
14
while idx < sentence.length and sentence[idx] == ' '
15
idx += 1
16
end
17
18
idx
19
end
20
21
def normalize_word!(sentence, idx)
22
if idx < sentence.length and sentence[idx] != ' '
23
sentence[idx] = sentence[idx].upcase
24
idx += 1
25
end
26
27
while idx < sentence.length and sentence[idx] != ' '
28
sentence[idx] = sentence[idx].downcase
29
idx += 1
30
end
31
32
idx
33
end
Copied!
Here's how you might test the student's solution:
1
require "minitest/autorun"
2
require "./normalize"
3
4
class Evaluate < Minitest::Test
5
def test_character
6
assert_equal "A", normalize("a"), "Your function should convert a single character"
7
assert_equal "A", normalize("A"), "Your function should convert a single character"
8
end
9
10
def test_no_mutate
11
sentence = "a"
12
normalize sentence
13
assert_equal "a", sentence, "Your function should not mutate the argument"
14
end
15
16
def test_word
17
assert_equal "Abc", normalize("abc"), "Your function should convert a single word"
18
assert_equal "Abc", normalize("ABC"), "Your function should convert a single word"
19
assert_equal "Abc", normalize("aBC"), "Your function should convert a single word"
20
assert_equal "Abc", normalize("Abc"), "Your function should convert a single word"
21
end
22
23
def test_sentence
24
assert_equal "Abc Def Ghi",
25
normalize("abc def ghi"),
26
"Your function should convert a sentence"
27
end
28
29
def test_multiple_whitespace
30
assert_equal " Abc Def Ghi ",
31
normalize(" abc def ghi "),
32
"Your function should keep multiple whitespaces"
33
end
34
end
Copied!
Last modified 1yr ago