Lemon
Homepage | User Guide | Development | Issues
DESCRIPTION
Lemon is a Unit Testing Framework that enforces a strict test structure mirroring the class/module and method structure of the target code. Arguably this promotes the proper technique for low-level unit testing and helps ensure good test coverage.
The difference between unit testing and functional testing, and all other forms of testing for that matter, is simply a matter of where the testing concern lies. The concerns of unit testing are the concerns of unit tests, which, in object-oriented design, drills down to individual methods.
IMPORTANT! As of v0.9+ the API has changed. The unit :name => "description"
notation is no longer supported.
EXAMPLE
Lemon tests are broken down into target class or module and target methods. Within these lie the actual tests.
Let's say we have a script 'mylib.rb' consisting of the class X:
class X
def a; "a"; end
end
An test case for the class would be written:
covers 'mylib'
testcase X do
setup "Description of setup." do
@x = X.new
end
method :a do
test "method #a does something expected" do
@x.a.assert.is_a? String
end
test "method #a does something else expected" do
@x.a.assert == "x"
end
end
end
The covers
method works just like require
with the exception that it records the file for reference --under certain scenarios it can be used to improve test coverage analysis.
The setup (also called the concern) is run for every subsequent test until a new setup is defined.
In conjunction with the #setup
method, there is a #teardown
method which can be used "tidy-up" after each test.
The #unit
method is also aliased as #methed
which is actually a bit more readable. Along with that there is class_unit
and it's alias class_method
for testing class-level methods. Also note that the test methods may be capitalized (e.g. `#TestCase'), if you prefer that style.
That is the bulk of the matter for writing Lemon tests. To learn about additional features not mentioned here, check-out the User Guide.
USAGE
Running Tests
Tests can be run using the lemons
command line tool.
$ lemons test test/cases/name_case.rb
Lemon utilizes the RubyTest universal test harness to run tests, the lemons test
command simply passes off control to rubytest
command. So the rubytest
command-line utility can also be used directly:
$ rubytest -r lemon test/cases/name_case.rb
Normal output is typically a dot progression. Other output types can be specified by the --format
or -f
option.
$ rubytest -r lemon -f tapy test/cases/name_case.rb
See RubyTest for more information.
Checking Test Coverage
Lemon can check per-unit test coverage by loading your target system and comparing it to your tests. To do this use the lemons coverage
command.
$ lemons coverage -Ilib test/cases/*.rb
The coverage tool provides class/module and method coverage and is meant as a "guidance system" for developers working toward complete test coverage. It is not a LOC (lines of code) coverage tool and should not be considered a substitute for one.
Generating Test Skeletons
Because of the one-to-one correspondence of test case and unit test to class/module and method, Lemon can also generate test scaffolding for previously written code. To do this, use the lemons generate
or lemons scaffold
command line utilities.
The generate
command outputs test skeletons to the console. You can use this output as a simple reference or redirect the output to a file and then copy and paste portions into separate files as desired. The scaffold
command will create actual files in your test directory. Other than that, and the options that go with it (e.g. --output
), the two commands are the same.
To get a set of test skeletons simply provide the files to be covered.
$ lemons generate lib/**/*.rb
The generator can take into account tests already written, so as not to include units that already have tests. To do this provide a list of test files after a dash (-
).
$ lemons generate -Ilib lib/**/*.rb - test/**/*.rb
Test skeletons can be generated on a per-file or per-case bases. By case is the default. Use the -f
/--file
option to do otherwise.
$ lemon scaffold -f lib/foo.rb
The default output location is test/
. You can change this with the -o/--output
option.
Generating test case scaffolding from code will undoubtedly strike test-driven developers as a case of putting the cart before the horse. However, it is not unreasonable to argue that high-level, behavior-driven, functional testing frameworks, such as Q.E.D. and Cucumber, are better suited to test-first methodologies. While test-driven development can obviously be done with Lemon, unit-testing best suited to testing specific, critical portions of code, or for achieving full test coverage for mission critical applications.
Test Directory
There is no special directory for Lemon tests. Since they are unit tests, test/
or test/unit/
are good choices. Other options are cases/
and test/cases
since each file generally defines a single test case.
COPYRIGHTS
Lemon Unit Testing Framework
Copyright (c) 2009 Thomas Sawyer, Rubyworks
Lemon is distributable in accordance with the FreeBSD license.
See the LICENSE.txt for details.