mirror of
https://github.com/cpm-cmake/CPM.cmake.git
synced 2025-11-25 05:37:28 -05:00
Split docs into multiple files. Complete tutorial. Reference.
This commit is contained in:
@@ -36,143 +36,8 @@ Writing tests makes use of the custom integration test framework in `lib.rb`. It
|
||||
* In case there are multiple test methods, they will be executed in the order in which they are defined.
|
||||
* The test methods should contain assertions which check for the expected state of things at varous points of the test's execution.
|
||||
|
||||
### More
|
||||
|
||||
### A simple tutorial
|
||||
|
||||
Let's create a test which checks that CPM.cmake can make a specific package available.
|
||||
|
||||
First we do some boilerplate.
|
||||
|
||||
```ruby
|
||||
require_relative './lib'
|
||||
|
||||
class MyTest < IntegrationTest
|
||||
# test that CPM.cmake can make https://github.com/cpm-cmake/testpack-adder/ available as a package
|
||||
def test_make_adder_available
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Now we have our test case class, and the single test method that we will require. Let's focus on the method's contents. The integration test framework provides us with a helper class, `Project`, which can be used for this scenario. A project has an assoiciated pair of source and binary directories in the temporary directory and it provides methods to work with them.
|
||||
|
||||
We start by creating the project:
|
||||
|
||||
```ruby
|
||||
prj = make_project
|
||||
```
|
||||
|
||||
`make_project` is method of IntegrationTest which generates a source and a binary directory for it based on the name of our test class and test method. The project doesn't contain anything yet, so let's create some source files:
|
||||
|
||||
```ruby
|
||||
prj.create_file 'main.cpp', <<~SRC
|
||||
#include <iostream>
|
||||
#include <adder/adder.hpp>
|
||||
int main() {
|
||||
cout << adder::add(1, 2);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Notable Idiosyncrasies
|
||||
|
||||
As an integration test framework based on a unit test framework it suffers from several idiosyncrasies. Make sure you familiarize yourself with them before writing integration tests.
|
||||
|
||||
**No shared instance variables between methods**
|
||||
|
||||
The runner will create an instance of the test class for each test method. This means that instance variables defined in a test method, *will not* be visible in another. For example:
|
||||
|
||||
```ruby
|
||||
class MyTest < IntegrationTest
|
||||
def test_something
|
||||
@x = 123
|
||||
assert_equal 123, @x # Pass. @x is 123
|
||||
end
|
||||
def tese_something_else
|
||||
assert_equal 123, @x # Fail! @x would be nil here
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
There are hacks around sharing Ruby state between methods, but we choose not to use them. If you want to initialize something for all test methods, use `setup`.
|
||||
|
||||
```ruby
|
||||
class MyTest < IntegrationTest
|
||||
def setup
|
||||
@x = 123
|
||||
end
|
||||
def test_something
|
||||
assert_equal 123, @x # Pass. @x is 123 thanks to setup
|
||||
end
|
||||
def tese_something_else
|
||||
assert_equal 123, @x # Pass. @x is 123 thanks to setup
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
**`IntegrationTest` makes use of `Test::Unit::TestCase#cleanup`**
|
||||
|
||||
After each test method the `cleanup` method is called thanks to Test::Unit. If you require the use of `cleanup` in your own tests, make sure you call `super` to also run `IntegrationTest#cleanup`.
|
||||
|
||||
```ruby
|
||||
class MyTest < IntegrationTest
|
||||
def cleanup
|
||||
super
|
||||
my_cleanup
|
||||
end
|
||||
# ...
|
||||
end
|
||||
```
|
||||
|
||||
**Try to have assertions in test methods as opposed to helper methods**
|
||||
|
||||
Test::Unit will display a helpful message if an assertion has failed. It will also include the line of code in the test method which caused the failure. However if an assertion is not in the test method, it will display the line which calls the method in which it is. So, please try, to have most assertions in test methods (though we acknowledge that in certain cases this is not practical). For example, if you only require scopes, try using lambdas.
|
||||
|
||||
Instead of this:
|
||||
|
||||
```ruby
|
||||
class MyTest < IntegrationTest
|
||||
def test_something
|
||||
do_a
|
||||
do_b
|
||||
do_c
|
||||
end
|
||||
def do_a
|
||||
# ...
|
||||
end
|
||||
def do_b
|
||||
# ...
|
||||
assert false # will display failed line as "do_b"
|
||||
end
|
||||
def do_c
|
||||
# ...
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
...write this:
|
||||
|
||||
```ruby
|
||||
class MyTest < IntegrationTest
|
||||
def test_something
|
||||
do_a = -> {
|
||||
# ...
|
||||
}
|
||||
do_b = -> {
|
||||
# ...
|
||||
assert false # will display failed line as "assert false"
|
||||
}
|
||||
do_c = -> {
|
||||
# ...
|
||||
}
|
||||
|
||||
do_a.()
|
||||
do_b.()
|
||||
do_c.()
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
* [A basic tutorial on writing integration tests.](tutorial.md)
|
||||
* [A brief reference of the integration test framework](reference.md)
|
||||
* Make sure you're familiar with the [idiosyncrasies](idiosyncrasies.md) of writing integration tests
|
||||
|
||||
Reference in New Issue
Block a user