Difference between revisions of "ISpec"

From IokeWiki
Jump to: navigation, search
Line 1: Line 1:
ISpec is a minimal port of the [http://rspec.info Ruby RSpec] framework for behavior-driven development. It supports the bare minimum to allow testing of Ioke itself. The current Ioke test suite is completely written in ISpec, and it seems to be a capable environment.
+
ISpec is a testing framework designed to enable behavior-driven development which takes its inspiration from [http://rspec.info RSpec], a similar Ruby framework. The current Ioke test suite is completely written in ISpec, and it seems to be a capable environment.
  
The ispec command line tool takes one argument -- "-f" to specify which format to print in. The default is "p" for progress, which only shows one dot for each test run. The "s" alternative shows the longer spec format. To run all tests in a directory with spec format:
 
  
 +
== Options ==
 +
 +
-f Specify the output format. Currently three formats are supported: s[pecdoc] (textual output with example titles), p[rogress] (one dot output for each test run) and h[tml] for use in continuous integration output and Textmate test runs.
 +
-p Limit files loaded to those matching pattern.
 +
-c Use colored output (default: true).
 +
-e Only execute examples matching name.
 +
-l Only execute examples defined at line_number.
 +
 +
For example:
 
<pre>ispec -fs test_dir</pre>
 
<pre>ispec -fs test_dir</pre>
 
This command will find all files ending in _spec.ik and run the specs defined in them. If a single file is specified, only the tests in that file will run. If more than one directory or file is specified on the command line, all the tests will be run together. Provided the spec files all use the ispec module, the files can be run directly with the ioke-command too.
 
This command will find all files ending in _spec.ik and run the specs defined in them. If a single file is specified, only the tests in that file will run. If more than one directory or file is specified on the command line, all the tests will be run together. Provided the spec files all use the ispec module, the files can be run directly with the ioke-command too.
 +
 +
== Usage ==
  
 
A full test file utilizing most of the parts of ISpec looks like this:
 
A full test file utilizing most of the parts of ISpec looks like this:
Line 42: Line 52:
 
This code first makes sure to use ISpec, then describes Foo. The describe method takes either kinds or texts describing what's under test. This can be nested arbitrarily deep. A test is defined with the &quot;it&quot; method, which takes a text describing the test first, and the implementation of the test as the second argument. If the second argument is left out, the test is considered pending.
 
This code first makes sure to use ISpec, then describes Foo. The describe method takes either kinds or texts describing what's under test. This can be nested arbitrarily deep. A test is defined with the &quot;it&quot; method, which takes a text describing the test first, and the implementation of the test as the second argument. If the second argument is left out, the test is considered pending.
  
Assertions are done using the &quot;should&quot; method. This returns an expectation that can check several different things against the original receiver. Using == is the simplest expectation and checks that a value equals another. By adding the not method call inbetween, the expectation is inversed. There are some predefined expectations. Except for ==, these are mimic, match and signal. The signal expectation makes sure that a condition is signalled in the code. The match expectation will check a text value against a regular expression. The mimic expectation checks whether an object mimics another.
+
Assertions are made using the &quot;should&quot; method. This returns an expectation that can check several different things against the original receiver. Using == is the simplest expectation and checks that a value equals another. By adding the not method call inbetween, the expectation is inversed. There are some predefined expectations. Except for ==, these are mimic, match and signal. The signal expectation makes sure that a condition is signalled in the code. The match expectation will check a text value against a regular expression. The mimic expectation checks whether an object mimics another.
  
 
The words &quot;be&quot; and &quot;have&quot; are ignored in the expectations. They are so called fluff words - that are only there to make it more readable.
 
The words &quot;be&quot; and &quot;have&quot; are ignored in the expectations. They are so called fluff words - that are only there to make it more readable.
  
 
If an expectation receives a message it doesn't know about, it uses pass to check a dynamic property. For example, something like &quot;foo should be same(x)&quot; will end up calling &quot;same?&quot; with x as an argument. The same thing happens in the above code to check for kind. There exists no kind expectation. Instead the kind checking will go check for &quot;kind?&quot;.
 
If an expectation receives a message it doesn't know about, it uses pass to check a dynamic property. For example, something like &quot;foo should be same(x)&quot; will end up calling &quot;same?&quot; with x as an argument. The same thing happens in the above code to check for kind. There exists no kind expectation. Instead the kind checking will go check for &quot;kind?&quot;.
 +
 +
== Mocking and stubbing ==
 +
 +
Ioke, as a prototype-based language, naturally supports replacement of cells for stubbing purposes. Sometimes, however, you want to do things like assert that particular cells are called a certain number of times, or ensure that the old values of cells are restored upon completion of a particular test. Enter mocking and stubbing.
 +
 +
ISpec supports the creation of mocks and stubs either on existing objects or through the creation of new objects designed to stand in for that purpose. In their simplest form, you can specify them as simple should assertions:
 +
 +
<source lang="ioke">foo should receive bar twice</source>
 +
 +
More complex cases allow you to specify key-value pairs:
 +
 +
<source lang="ioke">foo should receive(bar: 5, baz(6): 7)</source>
 +
 +
Finally, you can get arbitrarily complex:
 +
 +
<source lang="ioke">
 +
foo should receive(
 +
  baz(6) andReturn(7) atLeastOnce,
 +
  qux never,
 +
  mu(foo: "bar") andReturn(6, 7, 8)
 +
)</source>
 +
 +
Failure to satisfy the expectations will result in a test failure, signaling ISpec UnexpectedInvocation.
 +
 +
See the specs for ISpec mocking for more detailed usage examples.

Revision as of 19:34, 30 April 2009

ISpec is a testing framework designed to enable behavior-driven development which takes its inspiration from RSpec, a similar Ruby framework. The current Ioke test suite is completely written in ISpec, and it seems to be a capable environment.


Options

-f Specify the output format. Currently three formats are supported: s[pecdoc] (textual output with example titles), p[rogress] (one dot output for each test run) and h[tml] for use in continuous integration output and Textmate test runs.
-p Limit files loaded to those matching pattern.
-c Use colored output (default: true).
-e Only execute examples matching name.
-l Only execute examples defined at line_number.

For example:

ispec -fs test_dir

This command will find all files ending in _spec.ik and run the specs defined in them. If a single file is specified, only the tests in that file will run. If more than one directory or file is specified on the command line, all the tests will be run together. Provided the spec files all use the ispec module, the files can be run directly with the ioke-command too.

Usage

A full test file utilizing most of the parts of ISpec looks like this:

use("ispec")

describe(Foo,
  it("should have the correct kind",
    Foo should have kind("Foo")
    Foo kind should == "Foo"
    Foo kind should match(#/Fo+/)
  )

  it("should be possible to mimic",
    m = Foo mimic
    m should have kind("Foo")
    m should not be same(Foo)
    m should mimic(Foo)
  )

  describe("aMethod",
    it("should not return nil",
      Foo aMethod should not be nil
    )

    it("should return a number that can be multiplied",
      (Foo aMethod * 2) should == 12
    )
  )

  describe("aBadMethod",
    it("should signal a condition",
      fn(Foo aBadMethod) should signal(Condition Error BadBadBed)
    )
  )
)

This code first makes sure to use ISpec, then describes Foo. The describe method takes either kinds or texts describing what's under test. This can be nested arbitrarily deep. A test is defined with the "it" method, which takes a text describing the test first, and the implementation of the test as the second argument. If the second argument is left out, the test is considered pending.

Assertions are made using the "should" method. This returns an expectation that can check several different things against the original receiver. Using == is the simplest expectation and checks that a value equals another. By adding the not method call inbetween, the expectation is inversed. There are some predefined expectations. Except for ==, these are mimic, match and signal. The signal expectation makes sure that a condition is signalled in the code. The match expectation will check a text value against a regular expression. The mimic expectation checks whether an object mimics another.

The words "be" and "have" are ignored in the expectations. They are so called fluff words - that are only there to make it more readable.

If an expectation receives a message it doesn't know about, it uses pass to check a dynamic property. For example, something like "foo should be same(x)" will end up calling "same?" with x as an argument. The same thing happens in the above code to check for kind. There exists no kind expectation. Instead the kind checking will go check for "kind?".

Mocking and stubbing

Ioke, as a prototype-based language, naturally supports replacement of cells for stubbing purposes. Sometimes, however, you want to do things like assert that particular cells are called a certain number of times, or ensure that the old values of cells are restored upon completion of a particular test. Enter mocking and stubbing.

ISpec supports the creation of mocks and stubs either on existing objects or through the creation of new objects designed to stand in for that purpose. In their simplest form, you can specify them as simple should assertions:

foo should receive bar twice

More complex cases allow you to specify key-value pairs:

foo should receive(bar: 5, baz(6): 7)

Finally, you can get arbitrarily complex:

foo should receive(
  baz(6) andReturn(7) atLeastOnce, 
  qux never, 
  mu(foo: "bar") andReturn(6, 7, 8)
)

Failure to satisfy the expectations will result in a test failure, signaling ISpec UnexpectedInvocation.

See the specs for ISpec mocking for more detailed usage examples.