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.
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
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.
#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.
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
$ 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.
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
--file option to do otherwise.
$ lemon scaffold -f lib/foo.rb
The default output location is
test/. You can change this with the
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.
There is no special directory for Lemon tests. Since they are unit tests,
test/unit/ are good choices. Other options are
test/cases since each file generally defines a single test case.
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.