Difference between revisions of "ISpec"

From IokeWiki
Jump to: navigation, search
Line 8: Line 8:
 
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:
  
<pre>use(&quot;ispec&quot;)
+
<source lang="ioke">use("ispec")
  
 
describe(Foo,
 
describe(Foo,
   it(&quot;should have the correct kind&quot;,
+
   it("should have the correct kind",
     Foo should have kind(&quot;Foo&quot;)
+
     Foo should have kind("Foo")
     Foo kind should == &quot;Foo&quot;
+
     Foo kind should == "Foo"
 
     Foo kind should match(#/Fo+/)
 
     Foo kind should match(#/Fo+/)
 
   )
 
   )
  
   it(&quot;should be possible to mimic&quot;,
+
   it("should be possible to mimic",
 
     m = Foo mimic
 
     m = Foo mimic
     m should have kind(&quot;Foo&quot;)
+
     m should have kind("Foo")
 
     m should not be same(Foo)
 
     m should not be same(Foo)
 
     m should mimic(Foo)
 
     m should mimic(Foo)
 
   )
 
   )
  
   describe(&quot;aMethod&quot;,
+
   describe("aMethod",
     it(&quot;should not return nil&quot;,
+
     it("should not return nil",
 
       Foo aMethod should not be nil
 
       Foo aMethod should not be nil
 
     )
 
     )
  
     it(&quot;should return a number that can be multiplied&quot;,
+
     it("should return a number that can be multiplied",
 
       (Foo aMethod * 2) should == 12
 
       (Foo aMethod * 2) should == 12
 
     )
 
     )
 
   )
 
   )
  
   describe(&quot;aBadMethod&quot;,
+
   describe("aBadMethod",
     it(&quot;should signal a condition&quot;,
+
     it("should signal a condition",
 
       fn(Foo aBadMethod) should signal(Condition Error BadBadBed)
 
       fn(Foo aBadMethod) should signal(Condition Error BadBadBed)
 
     )
 
     )
 
   )
 
   )
)</pre>
+
)</source>
 
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.
  

Revision as of 09:26, 26 January 2009

ISpec is a minimal port of the 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.

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:

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.

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 done 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?".