Hello.

The next installment of Sorting algorithms in Ruby, will come out tomorrow night.

Before it does I wanted to use a separate post to present something that will be used in tomorrow’s post. I am doing it here because tomorrow’s post is already very long as it is.

**Reusing test logic**

Since the next two algorithms, Heap sort and Quicksort are more complex than my previous sorts, I wanted to make sure I had a robust testing suite.

When you consider the test cases for a given sorting algorithm, you can see that they can apply to any sorting algorithms. For this reason, I moved the actual testing code in a separate class named SortTest, which I will be able to reuse for any algorithms in the following installments.

Here it is:

class SortTest def initialize(sort_algorithm) @sort_algorithm = sort_algorithm end def test_empty_array empty_array = [] return test(empty_array, empty_array) end def test_array_with_one_element array_with_one_element = [1] return test(array_with_one_element, array_with_one_element.dup) end def test_ordered_array ordered_array = [1, 2, 4, 5, 6, 7] return test(ordered_array, ordered_array.dup) end def test_array_with_even_number_of_elements array_with_even_number_of_elements = [10, 23, 43, 45, 8, 2, 4, 9] sorted = array_with_even_number_of_elements.sort return test(array_with_even_number_of_elements, sorted) end def test_array_with_odd_number_of_elements array_with_odd_number_of_elements = [56, 3, 45, 11, 2, 3, 1] sorted = array_with_odd_number_of_elements.sort return test(array_with_odd_number_of_elements, sorted) end def test_medium_sized_array medium_sized_array = [6, 3, 5, 7, 1, 2, 8, 39, 23, 12, 34, 11, 32, 4, 13] sorted = medium_sized_array.sort return test(medium_sized_array, sorted) end def test_reversed_sorted_array reversed_sorted_array = [45, 33, 28, 25, 24, 19, 15, 14, 13, 12, 11, 10, 8, 4, 2, 1] sorted = reversed_sorted_array.sort return test(reversed_sorted_array, sorted) end def test_large_sized_array large_sized_array = [5, 2, 3, 8, 1, 3, 12, 10, 11, 6, 17, 13, 4, 9, 18 , 7, 15, 22, 40, 32, 34] sorted = large_sized_array.sort return test(large_sized_array, sorted) end def test_array_with_repeating_elements array_with_repeating_elements = [3, 5, 2, 7, 5, 2, 4, 5, 6, 5] sorted = array_with_repeating_elements.sort return test(array_with_repeating_elements, sorted) end private def test(initial_array, expected_result) actual_result = @sort_algorithm.sort(initial_array) result = actual_result == expected_result if not result puts puts "Expected result #{expected_result.inspect}" puts "Actual result #{actual_result.inspect}" end return result end end

And here is an example of it’s usage:

require 'test/unit' require './heap_sort.rb' require './sort_test.rb' class HeapSortTest < Test::Unit::TestCase def setup heap_sort = HeapSort.new @sort_test = SortTest.new(heap_sort) end def test_empty_array assert @sort_test.test_empty_array, "Empty array not corectly sorted" end def test_array_with_one_element assert @sort_test.test_array_with_one_element, "Array with one element not correctly sorted" end def test_ordered_array assert @sort_test.test_ordered_array, "Ordered array not correctly sorted" end def test_array_with_even_number_of_elements assert @sort_test.test_array_with_even_number_of_elements, "Array with even number of elements not correctly sorted" end def test_array_with_odd_number_of_elements assert @sort_test.test_array_with_odd_number_of_elements, "Array with odd number of elements not correctly sorted" end def test_medium_sized_array assert @sort_test.test_medium_sized_array, "Medium sized array not correctly sorted" end def test_reversed_sorted_array assert @sort_test.test_reversed_sorted_array, "Reversed sorted array not correctly sorted" end def test_large_size_array assert @sort_test.test_large_sized_array, "Large sized array not correctly sorted" end def test_test_array_with_repeating_elements assert @sort_test.test_array_with_repeating_elements, "Array with repeating elements not correctly sorted" end end

The reason I added the private test method in SortTest and custom assert messages in my HeapSortTest is because assert alone does not do a good job of reporting test failures.

The assert function will report a failure in this way:

1) Failure:

test_empty_array(HeapSortTest) [heap_sort_test.rb:12]:

false is not true.

Normally, if you use assert_operator or assert_equal you will get a more meaningful message, but with a simple assert the output is a little dry.

With the message parameter and the additional private test method here is the actual result:

Started

Expected result [1, 2, 4, 5, 6, 7]

Actual result [1, 2, 4, 5, 6]

F

Finished in 0.00767 seconds.1) Failure:

test_ordered_array(QuickSortTest) [quick_sort_out_of_place_test.rb:20]:

Ordered array not correctly sorted.

is not true.

Which is much better. You can clearly see what the problem is with just a quick glance. Ideally all test results should be this easy to read. With such clear messages, our tests will not only show us the errors, *they will serve as a first line of debugging information*.

I’m really learning a lot from your series on sorting algorithms in Ruby and this interlude on testing was awesome as well. I really appreciate you taking the time to put this series together and would encourage you

to do more of the same as I find your style is very clear, informative and easy to understand. Your really do a great job of explaining everything.

Again, thank you,

Mark

Thanks, that means a lot 🙂