A Io Language Testing Framework
Jasmine.Io is a Io Language port of the popular Behavior Driven Development testing framework for JavaScript.
The project was implemented as a learning exercise after reading the 7 languages in 7 weeks book, where Io is the second language introduced. The implementation makes relies on Io's strong metaprogramming capabilities..
Using Eerie:
eerie install git://github.com/bekkopen/jasmineio.git
Otherwise just clone the repository.
getFizzBuzz := method(number,
if(number % 3 == 0 and number % 5 == 0 , return "FizzBuzz")
if(number % 3 == 0, return "Fizz")
if(number % 5 == 0, return "Buzz")
number
)
describe("FizzBuzz",
it("Should return Fizz for divisible of three",
expect(getFizzBuzz(3)) toBe("Fizz")
),
it("Should return Buzz for divisible of five",
expect(getFizzBuzz(5)) toBe("Buzz")
),
it("Should return FizzBuzz for divisible of three and five",
expect(getFizzBuzz(15)) toBe("FizzBuzz")
),
it("Should return number if not divisible by three or five",
expect(getFizzBuzz(2)) toBe(2)
)
)
If you've installed jasmineio
with Eerie, execute the spec by calling:
jasmineio fizzbuz_spec.io
Otherwise run the script jasmineio
from bin
directory:
$ io jasmineio fizzbuzz_spec.io
If you do not specify a spec-file to run, Jasmine.Io will recursively walk your working directory, executing any file name ending with _spec.io
.
$ jasmineio fizzbuzz_spec.io
FizzBuzz
✓ Should return Fizz for divisible of three: passed
✓ Should return Buzz for divisible of five: passed
✓ Should return FizzBuzz for divisible of three and five: passed
✓ Should return number if not divisible by three or five: passed
Results: 4 specs, 0 failures
Extending Jasmine.Io with custom matchers are dead simple. You simply add a new method to the Matcher prototype that evaluates to true or false. Jasmine.Io will generate resenoable error messages automatically, or you can choose to customize the error message yourself.
Matcher toBeLessThan := method(expected, actual < expected)
Matcher toBeGreaterThan := method(expected,
if(actual > expected, return false)
self message := actual .. " is not greater than " .. expected
false
)
describe("Custom matchers",
it("is possible to add matchers by adding a method to the Matcher prototype",
expect(1) toBeLessThan(2)
),
it("should error messages generated automatically",
expect(2) toBeLessThan(1)
),
it("is possible to customize the error message if you want to",
expect(1) toBeGreaterThan(2)
)
)
$ jasmineio matcher_spec.io
Custom matchers
✓ is possible to add matchers by adding a method to the Matcher prototype: passed
ϰ should error messages generated automatically: Expected 2 to be less than 1
ϰ is possible to customize the error message if you want to: 1 is not greater than 2
Results: 3 specs, 2 failures
Jasmine.io supports spies, which allow you to record and verify calls made to a method:
spy := spyOn(target, "writeln")
target doSomething
expect(spy) toHaveBeenCalledWith("the value we expect")
You can also inspect the spy's calls
property, which is a list with one element per call received. Each element is a list of arguments. If you want to call the real method in addition to recording calls, use andCallThrough
. You can also use andForwardTo
to call any method on any object or andCallFake
to call a block:
spy := spyOn(target, "writeln") andCallThrough
// Alternately:
spy := spyOn(target, "writeln") andForwardTo(someObject, "someMethodName")
// Alternately:
spy := spyOn(target, "writeln") andCallFake(block(/* do something */))
target doSomething
expect(spy) toHaveBeenCalledWith("the value we expect")
$ jasmineio spy_spec.io
Spies
✓ should throw if the object is nil
✓ should throw if the method name is nil
✓ should provide the spy in the method's scope slot
✓ should start with an empty call list
✓ should store the arguments used to call the spy
Results: 5 specs, 0 failures
toHaveBeenCalled matcher
✓ should succeed if the spy was called
✓ should fail if the spy wasn't called
Results: 2 specs, 0 failures
toHaveBeenCalledWith matcher
✓ should succeed if the spy was called with the right arguments
✓ should fail if the spy wasn't called
✓ should fail if the spy was called with the wrong arguments
Results: 3 specs, 0 failures