public
Created

Detective

  • Download Gist
README.markdown
Markdown

Detective

What is it?

Simply put, this is a ruby testing library which asks questions in order to determine compliance.

That is, you ask the user questions with "ask", and test results with "expect". You can also give instructions with "instruct".

The entire testing suite is evaluated using the command-line. e.g.

$ detective ./example_tests.rb

We should follow instructions.
Follow instructions, press enter [press RETURN to continue]

Enter 5: 
5

How do i write my tests?

In a similar fashion to rspec, you put your tests in "describe" or "it" blocks.

describe "Cool feature" do
  instruct("We will be testing this cool feature")
  it "should show the correct word" do
    instruct("Go to coolwebapp.com")
    ask("What does it say in the middle of the front page?").expect("Cheezburger")
  end
end

How do i run it?

detective tests1.rb tests2.rb ...

Have fun!

detective.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
#!/usr/bin/env ruby
# detective
# Tests by asking the user questions
#
# NOTE: requires ruby 1.9.2 and the rainbow gem.
#
# Usage:
# detective [list of ruby test files]
#
# Syntax:
# describe "A test" do
# instruct "Go to google"
# ask("What is written on the first button?").expect("Google Search")
# end
#
#
require 'fiber'
require 'rainbow'
 
module Detective
# Ask question. e.g.
# ask "Where were you last night?"
def ask(question)
@last_question = question
@last_result = Fiber.yield [:ask, question]
return self
end
 
# Instruct the user. e.g.
# instruct "You have the right to remain silent"
def instruct(question)
Fiber.yield [:instruct, question]
return self
end
 
# Expect a result from the last question. e.g.
# ask("When did you last see M. Ratchett alive?").expect("last evening")
def expect(result)
if (@last_result||'').strip != result.to_s.downcase
Fiber.yield [:fail, @last_question, @last_result, result]
end
end
# Describe a test. e.g.
# describe("The suspect") { ask("How many fingers am i holding up?").expect(1) }
def describe test, &block
Fiber.yield [:describe, test]
yield
Fiber.yield [:describe_end, test]
end
alias_method :it, :describe
end
 
def run_suite(files)
fib = Fiber.new do
include Detective
files.each { |f| require f }
end
total_test = 0
total_pass = 0
test_results = []
 
begin
result = nil
describe_stack = []
while (command = fib.resume(result)) and !command.nil? and command != :end
result = nil
case command[0]
when :instruct
if describe_stack[-1][1]
puts "#{command[1]} [press RETURN to continue]"
result = STDIN.readline
end
when :ask
if describe_stack[-1][1]
puts "#{command[1]}: "
result = STDIN.readline.downcase
end
when :describe
describe_stack << [command[1], true]
puts "\n#{describe_stack.map{|d|d[0]}.join(' ')}.\n"
total_test += 1
when :describe_end
test_results << ["#{describe_stack.map{|d|d[0]}.join(' ')}.", describe_stack[-1][1]]
total_pass += 1 if describe_stack.pop[1]
when :fail
describe_stack[-1][1] = false
end
end
rescue FiberError
rescue Exception => e
puts e.inspect
puts e.backtrace
end
puts "\n"
test_results.reverse.each do |test|
puts test[0].color(test[1] ? :green : :red)
end
puts "\n#{total_pass} / #{total_test} Tests passed".color(total_pass == total_test ? :green : :red)
exit total_pass == total_test ? 0 : 1
end
 
run_suite(ARGV)
example_tests.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# Our cool tests
describe "We should follow instructions" do
instruct("Follow instructions, press enter")
ask("Enter 5").expect(5)
it "even if they dont make sense" do
instruct("Enter 22 instead of 1")
ask("Enter 1").expect(22)
end
end
 
describe "More tests" do
instruct("We will now ask you several more questions")
ask("Enter lolcat").expect('lolcat')
it "should drive the user crazy" do
ask("Are you crazy yet?").expect('yes')
end
ask("Do you want me to ask you another question?").expect('yes')
instruct("I cant think of another question, goodbye!")
end

Nice approach of testing.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.