Skip to content

Instantly share code, notes, and snippets.

@jamesu
Created July 5, 2011 09:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamesu/1064566 to your computer and use it in GitHub Desktop.
Save jamesu/1064566 to your computer and use it in GitHub Desktop.
Detective

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!

#!/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)
# 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
@asaaki
Copy link

asaaki commented Jul 17, 2011

Nice approach of testing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment