CS312 - Spring 2012 - Class 6
administrative
- assignment 1 observations
- break down code into smaller functions!
- any time you find yourself writing function of more than 5-10 lines of code, think if it's necessary
- to_s is like toString in java and should return a string
- write functions for repetition in code
- use ternary operator to shorten things
- assignment 3
- anyone need a partner?
- read over the entire handout asap!
- ask me if you need any clarifications
- make sure you follow the directions carefully
- before you submit make sure you're submitting everything
- exercise in following directions :)
unit testing in Ruby
- there are many other types of assertions
- see pg. 208 in the book
- all the asserts also contain a refute (which just checks the opposite)
- assert_raises for checking that an error is thrown
- assert_nil to check if the result is nil
- ...
- test_linked_list.rb in
UnitTesting code
has more tests
- test_remove_empty
- the assert_nil has a second, optional argument
- allows us to include additional information
- test_to_s
- upto iterates starting at a number up to and including a given number
- we can convert from a Range (1..10) to a list using the "entries" method
- test_add_and_remove_intertwined
- you can declare helper methods if you want
- any method that does NOT start with test will not be run as a test
- test_each_with_index
- keep our own counter for the index
- we know what values to expect
- check both the counter and the value
- makes sure the list hasn't been changed after
- if we run it
Run options:
# Running tests:
......
Finished tests in 0.000711s, 8438.8186 tests/s, 53445.8509 assertions/s.
6 tests, 38 assertions, 0 failures, 0 errors, 0 skips
test suites
- look at test_linked_list_node.rb in
UnitTesting code
- note that we have one test class per class we're testing (generally)
- what do these two tests check?
- test_initialize just checks to make sure what we pass to initialize gets set to the value
- test_initialize_empty
- makes sure that we can't create a Node without a value
- the assert_raises checks to make sure that a particular error was raised for a given block of code
- it takes an argument, which is the name of the error
- if you're not sure what error will be raised, run the command without the assert and see what error is raised
- then put this in as the argument for assert_raises
- it also takes a block of code, which it will execute and see if the error is raised
- if we work on a project long enough, we will likely end up with lots of tests
- we can organize these tests into test suites that are groups of related unit tests
- To create a test suite
- create a new .rb file in the test directory
- by convention, the name should start with ts_ (for "test suite")
- for each of the test classes you'd like to run put them in this file with a require_relative
- remember that require (and require_relative) simply run the required file/class
- for example, ts_linked_list.rb in
UnitTesting code
is a test suite for the LinkedList class
- we can then run this test
$ ruby -I lib test/ts_linked_list.rb
Run options:
# Running tests:
........
Finished tests in 0.002708s, 2954.2097 tests/s, 15140.3250 assertions/s.
8 tests, 41 assertions, 0 failures, 0 errors, 0 skips
controlling the unit test run
- we can alter the behavior of the run from the command-line
- if we add "-v" it prints out more debugging information
$ ruby -I lib test/ts_linked_list.rb -v
Run options: -v
# Running tests:
TestLinkedList#test_add_and_remove = 0.00 s = .
TestLinkedList#test_add_and_remove_better = 0.00 s = .
TestLinkedList#test_add_and_remove_intertwined = 0.00 s = .
TestLinkedList#test_each_with_index = 0.00 s = .
TestLinkedList#test_remove_empty = 0.00 s = .
TestLinkedList#test_to_s = 0.00 s = .
TestLinkedListNode#test_initialize = 0.00 s = .
TestLinkedListNode#test_initialize_empty = 0.00 s = .
Finished tests in 0.002367s, 3379.8057 tests/s, 17321.5040 assertions/s.
8 tests, 41 assertions, 0 failures, 0 errors, 0 skips
- we can run particular test(s) with the -n flag with allows us to specify a particular test:
$ ruby -I lib test/ts_linked_list.rb -n test_add_and_remove
Run options: -n test_add_and_remove
# Running tests:
.
Finished tests in 0.001798s, 556.1735 tests/s, 1668.5206 assertions/s.
1 tests, 3 assertions, 0 failures, 0 errors, 0 skips
- or a regular expression match of tests:
$ ruby -I lib test/ts_linked_list.rb -n /add/ -v
Run options: -n /add/ -v
# Running tests:
TestLinkedList#test_add_and_remove = 0.00 s = .
TestLinkedList#test_add_and_remove_better = 0.00 s = .
TestLinkedList#test_add_and_remove_intertwined = 0.00 s = .
Finished tests in 0.001906s, 1573.9769 tests/s, 7345.2256 assertions/s.
3 tests, 14 assertions, 0 failures, 0 errors, 0 skips
- these can be done at the test suite level or for a single file
Test-Driven Experiment
-
http://www.cs.middlebury.edu/~dkauchak/classes/cs312/handouts/binary_search/
- I will give you a function to write along with unit tests for the function. Half of the class will implement tests first and then the function; the other half will write the function then the unit tests. You will be timed on how long it takes for you to finish as well as correctness. When you're done, you can record your time and download the unit tests from the course web page to check your answer.
- Write:
- Implement binary search in a function called binary_search that takes a sorted array as a parameter and a value. If the value occurs in the array, return the index at which it occurs in the array (if multiple occur, any index is fine). If it does not occur, return nil. You may assume that the value and the entries in the array support the comparison operators.
- Write one or more unit tests to test your function.