Tokyo - super-simple testing library for Ruby
Its base API consist of just 10 memorable methods:
- spec, context
- before, around, after
- test
- assert, refute
- skip, fail
Assertions uses native Ruby methods so no need to remember contrived ones.
Forget about repeatedly scanning documentation, just use methods Ruby already provides.
Want to check whether something is nil? Use nil? method:
assert(something).nil?
Want to check whether some array contains some value? Use include? method:
assert(some_array).include? some_value
Need to check equality? Nothing simpler:
assert(something) == something_else
Perhaps match?
assert(something) =~ something_else
Or any?
assert(some_array).any? {|v| v > 0}
Whatever. Use Ruby rather than contrived APIs.
And when you need to cook your own assertions simply use assert method to define them:
# defining a custom assertion
assert :is_a_pizza do |something|
something =~ /Cheese/ && something =~ /Olives/
end
# using it inside tests
test 'food' do
assert(something).is_a_pizza
end
Installation
Add this line to your application's Gemfile:
gem 'tokyo'
And then execute:
$ bundle
Or install it yourself as:
$ gem install tokyo
Usage
Add require 'tokyo' to your Rakefile.
Then create a task and use Tokyo.run:
task :test do
Tokyo.run
end
By default it will load *_spec.rb and *_test.rb files from ./spec and ./test folders.
If you named your test files differently use Tokyo.run with your pattern:
# search for test_*.rb files in ./tests folder
task :test do
Tokyo.run 'tests/test_*.rb'
end
If you want to run tests directly just use tokyo in your terminal:
tokyo
This will load *_spec.rb and *_test.rb files from ./spec and ./test folders.
If your tests have different naming conventions call tokyo command with a pattern.
For ex. load test_*.rb files in ./tests folder:
tokyo tests/test_*.rb
Specs
Specs are defined by using spec method. It requires a single argument - the spec label.
It can be whatever but nil(which is used for another purpose, as shown below).
# defining a spec
spec Apple do
# and tests inside it
test :color do
end
end
Nested contexts can be used for splitting logic:
spec Greens do
context Fruits do
context Apple do
end
end
end
Specs are modules
spec method returns a module. Specs including that module will inherit all tests:
FruitsTests = spec Fruits do
# some tests
end
spec Apple do
# inheriting tests from FruitsTests spec
include FruitsTests
# defining own specs
end
If you want a module that just holds tests without run them, use nil for label:
FruitsTests = spec nil do
# tests defined here will run only on specs that includes FruitsTests
end
Global setups
spec method can also be used for defining a superset of instructions that will be run by all specs.
For this to work spec method should be called without arguments.
Then the given block will run equally on all consequent specs.
Multiple global setups can be defined and they will run inside specs in the order they was defined.
# supposedly in setup.rb
spec do
include SomeModule
end
# somewhere in test files
spec Fruits do
# this spec will include SomeModule implicitly
end
Before, around, after
Run some code before every test:
spec 'Fruits' do
before { @fruit = Fruit.new }
# tests here will have @fruit variable defined
end
When you need to run some code after every test simply use after method same way as before.
There is also an around method that will wrap each test into a block.
The difference is you have to call test manually:
spec 'Fruits' do
around do |test|
# initialization stuff
test.call
# teardown stuff
end
# tests here will run inside around block
end
There is no way to run code before/around/after specific tests.
If you have tests that needs specific initialization/teardown logic put them into a separate context.
Skipping tests and specs
When you need to skip a test simply use skip method with a reason provided as first argument:
test 'something' do
# any code before skip will still run
skip 'will test this later'
# code here wont run
end
skip also works for entire specs:
spec Fruits do
skip 'concentrating on Vegetables for now...'
# tests here wont run
end
Explicit failures
When you need to throw a failure with a custom message use fail method:
test 'something' do
@a > @b || fail("#a should be greater than #b")
# code here wont run
end
raise helper
raise allows to check whether some code raises a specific or any exception.
Check the block raises whatever exception:
assert {some code}.raise
Check the block raises a NameError exception:
assert {some code}.raise NameError
Check the block raises a FruitError exception that match /apple/:
assert {some code}.raise FruitError, /apple/
Use a block to check raised exception:
assert {some code}.raise {|e| e.is_a? FruitError}
Also alternative syntax available:
expect {some code}.to_raise ...
throw helper
Check the block throws whatever symbol:
assert {some code}.throw
Check the block throws :ok symbol:
assert {some code}.throw :ok
Use a block to validate thrown symbol:
assert {some code}.throw {|s| s == :ok}
Also alternative syntax available:
expect {some code}.to_throw ...
Development
Make sure bundler is installed then run bundle install to install all dependencies.
Make your changes and run rake to check all tests pass.
Contributing
- Fork it ( https://github.com/[my-github-username]/tokyo/fork )
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request