Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Literate testing?

Reply
Thread Tools

Literate testing?

 
 
Massimiliano Mirra - bard
Guest
Posts: n/a
 
      08-27-2004

I was documenting a class and found myself often copying unit tests
and pasting them as examples. I think I also read something about
tests embedded in doc strings in Python. So in the interest of DRY I
figured something like this could be desirable:

class Calculator
extend Literate

example
# Addition
add(2, == 10
end

def add(a, b)
return a + b
end
end

I then came up with a stupid but working proof of concept:

class Calculator
extend Literate

example(__FILE__, __LINE__) do |calc|
# Addition
calc.add(2, == 10
end

def add(a, b)
return a + b
end

example(__FILE__, __LINE__) do |calc|
# Integer division
calc.div(10, 2) == 5
end

def div(a, b)
return a / b + 1
end
end

When examples are run as tests and a test does not pass (as the div
example above), this is the output:

Test passed at line 17.
Test failed at line 27:
# Integer division
calc.div(10, 2) == 5

This is the rest:

module Literate
def examples
@examples ||= []
end

def example(file, line, &example)
@examples ||= []
@examples << [file, line, example]
end
end

Calculator.examples.each do |file, line, example|
c = Calculator.new
if example.call(c)
puts "Test passed at line #{line}."
else
puts "Test failed at line #{line}:"
puts File.readlines(file)[line, 2]
end
end

What do you think?



Massimiliano

 
Reply With Quote
 
 
 
 
Joel VanderWerf
Guest
Posts: n/a
 
      08-27-2004
Massimiliano Mirra - bard wrote:
> class Calculator
> extend Literate
>
> example(__FILE__, __LINE__) do |calc|

...

Since you are passing a block, you can get the file and line from it, as in:


def get_fl(&bl)
eval "[__FILE__, __LINE__]", bl
end

class Foo
puts get_fl {}
puts [__FILE__, __LINE__]
end


 
Reply With Quote
 
 
 
 
Joel VanderWerf
Guest
Posts: n/a
 
      08-27-2004
Massimiliano Mirra - bard wrote:
> I was documenting a class and found myself often copying unit tests
> and pasting them as examples. I think I also read something about
> tests embedded in doc strings in Python. So in the interest of DRY I
> figured something like this could be desirable:
>
> class Calculator
> extend Literate
>
> example
> # Addition
> add(2, == 10
> end
>
> def add(a, b)
> return a + b
> end
> end
>
> I then came up with a stupid but working proof of concept:
>
> class Calculator
> extend Literate
>
> example(__FILE__, __LINE__) do |calc|
> # Addition
> calc.add(2, == 10
> end


Are you planning to extract the example from the source code and
generate documentation files? This could be done using the file and line
information and some parsing or just good guesses about indentation.


 
Reply With Quote
 
Mauricio FernŠndez
Guest
Posts: n/a
 
      08-27-2004
On Sat, Aug 28, 2004 at 05:40:33AM +0900, Massimiliano Mirra - bard wrote:
>
> I was documenting a class and found myself often copying unit tests
> and pasting them as examples. I think I also read something about
> tests embedded in doc strings in Python. So in the interest of DRY I
> figured something like this could be desirable:
>
> class Calculator
> extend Literate
>
> example
> # Addition
> add(2, == 10
> end
>
> def add(a, b)
> return a + b
> end
> end
>
> I then came up with a stupid but working proof of concept:
>
> class Calculator
> extend Literate
>
> example(__FILE__, __LINE__) do |calc|
> # Addition
> calc.add(2, == 10
> end


I believe you can make it look a bit better by using Kernel#caller
and Module#method_added; it would also be nice to generate test
cases for Test::Unit (for instance by defining the test_* methods in
MyClass::LiterateTests so that they can be included in a test suite
later).

Reminds me of Florian GroŖ' 'test extractor' [109712].
It works "the other way around" though, by extracting the tests from the
comments (similar to what you describe for Python).

--
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com



 
Reply With Quote
 
Massimiliano Mirra - bard
Guest
Posts: n/a
 
      08-27-2004
Mauricio Fern√°ndez <(E-Mail Removed)> writes:

> I believe you can make it look a bit better by using Kernel#caller
> and Module#method_added;


I confess I have absolutely no idea how.

> it would also be nice to generate test
> cases for Test::Unit (for instance by defining the test_* methods in
> MyClass::LiterateTests so that they can be included in a test suite
> later).


Nice. I tried, and the last call shows test_* methods get defined,
but Test::Unit says `No tests were specified.'.


require "test/unit"

module Literate
def method_missing(id, *args, &block)
if id.to_s =~ /example_/
name = Regexp.last_match.post_match
self::LiterateTests.send(:define_method, "test_#{name}".intern, &block)
else
super(id, *args, &block)
end
end
end

class Calculator
extend Literate

module LiterateTests
end

example_add do
assert @calc.add(2, == 10
end

def add(a, b)
return a + b
end

example_div do
assert @calc.div(10, 2) == 5
end

def div(a, b)
return a / b + 1
end
end

class TestCalculator < Test::Unit::TestCase
include Calculator::LiterateTests

def setup
@calc = Calculator.new
end
end

p TestCalculator.public_instance_methods
 
Reply With Quote
 
Massimiliano Mirra - bard
Guest
Posts: n/a
 
      08-27-2004
Joel VanderWerf <(E-Mail Removed)> writes:

> Are you planning to extract the example from the source code and
> generate documentation files?


I'd rather say `hoping', but yes, that would be the purpose.

> This could be done using the file and line
> information and some parsing or just good guesses about indentation.


Yep. Or by hacking rdoc a bit.

Thanks for the bit on eval.

Massimiliano
 
Reply With Quote
 
Mauricio FernŠndez
Guest
Posts: n/a
 
      08-30-2004
On Sat, Aug 28, 2004 at 07:45:33AM +0900, Massimiliano Mirra - bard wrote:
> Mauricio FernŠndez <(E-Mail Removed)> writes:
>
> > I believe you can make it look a bit better by using Kernel#caller
> > and Module#method_added;

>
> I confess I have absolutely no idea how.
>
> > it would also be nice to generate test
> > cases for Test::Unit (for instance by defining the test_* methods in
> > MyClass::LiterateTests so that they can be included in a test suite
> > later).

>
> Nice. I tried, and the last call shows test_* methods get defined,
> but Test::Unit says `No tests were specified.'.


I think you were bitten by the IMHO bug explained in
http://blade.nagaokaut.ac.jp/cgi-bin...ruby-core/2829

--
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com



 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Literate Programming Hans Georg Schaathun Python 10 04-11-2011 04:39 PM
Literate programs in Python Paul Miller Python 6 05-14-2008 06:04 AM
How to literate a const char* silverburgh.meryl@gmail.com C Programming 2 07-15-2007 12:29 AM
[QUIZ] Literate Ruby (#102) Ruby Quiz Ruby 10 11-22-2006 05:36 PM
XMLMind and Literate Programming Mike Maxwell XML 2 11-03-2004 02:13 PM



Advertisments