The Problem
Now that I created my first tcltest module, I want to break up my tests into several modules. I also want to separate my tests from my source code.
The Solution
In this tutorial, I will pick up from the last time. Recall that in the previous post, I created the first test module, but both the source code (sum.tcl) and the tests are in the same directory. While this arrangement is fine for small projects, as they grow, I will want to separate the source code from the test code to improve code management.
From the previous tutorial, the directory contains 3 files:
- sum.tcl – The software under test (SUT)
- all.tcl – The “main” test script
- sum.test – The test module which tests function sum
To separate the source code from the tests, we start by creating two sub directories: src and tests and move the files to these directories according to their roles:
mkdir src tests mv sum.tcl src mv all.tcl sum.test tests
Next, we go into the tests directory and attempt to run the tests again:
cd tests tclsh all.tcl
This time, we ran into a error because the file sum.tcl is no longer in the same directory with the test module:
Test file error: couldn't read file "sum.tcl": no such file or directory while executing "source sum.tcl" (file "/home/haiv/src/tcl/tcltest_part2/tests/sum.test" line 7)
To fix it, modify line 7 of sum.test so it reads:
source ../src/sum.tcl
Now, run the tests again and everything should work as before. At this point, we successfully separate the tests from the source code. From now on, our test modules will go into the tests directory and the source code will go into the src directory.
Next, we are adding a new function: square, which returns the square of a number. The new function resides in src/square.tcl:
proc square {x} { expr {$x * $x} }
Our next step is to add the tests for function square. Again, for the sake of brevity, i will ommit the test descriptions, but encourage you to add them to enhance test readablity.
# square.test package require tcltest namespace import ::tcltest::* # Software under test source ../src/square.tcl test square_ofZeroExpectsZero { Test: [square 0] == 0 } -body { square 0 } -result 0 test square_ofNegativeExpectsPositive {} -body { square -9 } -result 81 test square_ofPositiveExpectsPositive {} -body { square 19 } -result 361 cleanupTests
Notes: This test module is very similar to the sum.test module so it is tempting to copy and paste. Please keep in mind that when you copy and paste, be sure to check the code. Here is the tests output:
Tests running in interp: /usr/bin/tclsh Tests located in: /home/haiv/src/tcl/tcltest_part2/tests Tests running in: /home/haiv/src/tcl/tcltest_part2/tests Temporary files stored in /home/haiv/src/tcl/tcltest_part2/tests Test files run in separate interpreters Running tests that match: * Skipping test files that match: l.*.test Only running test files that match: *.test Tests began at Mon Mar 28 07:13:18 PM PDT 2011 square.test sum.test Tests ended at Mon Mar 28 07:13:18 PM PDT 2011 all.tcl: Total 6 Passed 6 Skipped 0 Failed 0 Sourced 2 Test Files.
Note that the output now shows 2 files: square.test and sum.test. Also note that square.test precedes sum.test: tcltest run them in alphabetical order of file names. However, do not assume that order: in general, unit test cases should be independent of each other.
Summary
This tutorial shows you how to separate the tests from the source code for better code management. It also demonstrate a multi-module test suite. In the next installment, I am going to go into test filters.