Skip to content

Instantly share code, notes, and snippets.

@PeterHajdu
Created November 1, 2012 16:41
Show Gist options
  • Save PeterHajdu/3994920 to your computer and use it in GitHub Desktop.
Save PeterHajdu/3994920 to your computer and use it in GitHub Desktop.
rspec cucumber test

Description

This is a test project to practice rspec and cucumber

#!/usr/bin/env ruby
$LOAD_PATH.unshift File.expand_path('../../lib',__FILE__)
require 'codebreaker'
def generate_secret_code
options = %w[ 1 2 3 4 5 6 ]
( 1..4 ).map { options.delete_at( rand( options.length ) ) }.join
end
game = Codebreaker::Game.new( STDOUT )
game.start( generate_secret_code )
while guess = gets.chomp
game.guess( guess )
end
require 'codebreaker/game'
require 'codebreaker/marker'
Feature: code-breaker starts game
As a code-breaker
I want to start a game
So that I can break the code
Scenario: start game
Given I am not yet playing
When I start a new game
Then I should see "Welcome to Codebreaker!"
And I should see "Enter guess:"
class Output
def messages
@messages ||= []
end
def puts( message )
messages << message
end
end
def output
@output ||= Output.new
end
Given /^I am not yet playing$/ do
end
When /^I start a new game$/ do
game = Codebreaker::Game.new( output )
game.start( '1234' )
end
Then /^I should see "(.*?)"$/ do | message |
output.messages.should include( message )
end
Given /^the secret code is "(.*?)"$/ do | secret |
@game = Codebreaker::Game.new( output )
@game.start( secret )
end
When /^I guess "(.*?)"$/ do | guess |
@game.guess( guess )
end
Then /^the mark should be "(.*?)"$/ do | mark |
output.messages.should include( mark )
end
Feature: code-breaker submits guess
The code-breaker submits a guess of four numbers. The game marks the guess with + and - signs.
For each number in the guess that matches the number and position of a number in the secret code,
the mark includes one + sign. For each number in the guess that matches the number but not the
position of a number in the secret code, the mark includes one - sign.
Each position in the secret code can only be matched once. For example, a guess of 1344 against
a secret code of 1234 would get three plus signs: one for each of the exact matches in the first,
third and fourth positions. The number match in the second position would be ignored.
Scenario Outline: submit guess
Given the secret code is "<code>"
When I guess "<guess>"
Then the mark should be "<mark>"
Scenarios: no matches
| code | guess | mark |
| 1234 | 5555 | |
Scenarios: 1 number correct
| code | guess | mark |
| 1234 | 1555 | + |
| 1234 | 2555 | - |
Scenarios: 2 numbers correct
| code | guess | mark |
| 1234 | 5254 | ++ |
| 1234 | 5154 | +- |
| 1234 | 2545 | -- |
Scenarios: 3 numbers correct
| code | guess | mark |
| 1234 | 5234 | +++ |
| 1234 | 5134 | ++- |
| 1234 | 5124 | +-- |
| 1234 | 5123 | --- |
Scenarios: all numbers correct
| code | guess | mark |
| 1234 | 1234 | ++++ |
| 1234 | 1243 | ++-- |
| 1234 | 1423 | +--- |
| 1234 | 4321 | ---- |
Scenarios: matches with duplicates
| code | guess | mark |
| 1234 | 1155 | + |
| 1234 | 5115 | - |
| 1134 | 1155 | ++ |
| 1134 | 5115 | +- |
| 1134 | 5511 | -- |
| 1134 | 1115 | ++ |
| 1134 | 5111 | +- |
$LOAD_PATH << File.expand_path( '../../../lib', __FILE__ )
require 'codebreaker'
module Codebreaker
class Game
def initialize( output )
@output = output
end
def start( secret )
@secret = secret
@output.puts "Welcome to Codebreaker!"
@output.puts "Enter guess:"
end
def guess( guess )
marker = Marker.new( @secret, guess )
@output.puts '+' * marker.exact_match_count +
'-' * marker.number_match_count
end
end
end
require_relative './spec_helper'
module Codebreaker
describe Game do
let( :output ) { double( 'output' ).as_null_object }
let( :game ) { Game.new( output ) }
describe "#start" do
it "sends a welcome message" do
output.should_receive( :puts ).with( "Welcome to Codebreaker!" )
game.start( '1234' )
end
it "prompts for the first guess" do
output.should_receive( :puts ).with( "Enter guess:" )
game.start( '1234' )
end
end
describe "#guess" do
it "sends the mark to output" do
game.start( '1234' )
output.should_receive( :puts ).with( '++++' )
game.guess( '1234' )
end
end
end
end
Feature: greeter says hello
In order to start learning RSpec and Cucumber
As a reader of The RSpec Boo
I want a greeter to say Hello
Scenario: greeter says hello
Given a greeter
When I send it the greet message
Then I should see "Hello Cucumber!"
class RSpecGreeter
def greet
'Hello RSpec!'
end
end
describe "RSpec Greeter" do
it "should say 'Hello RSpec!' when it receives the greet() message" do
greeter = RSpecGreeter.new
greeting = greeter.greet
greeting.should == "Hello RSpec!"
end
end
class CucumberGreeter
def greet
"Hello Cucumber!"
end
end
Given /^a greeter$/ do
@greeter = CucumberGreeter.new
end
When /^I send it the greet message$/ do
@message = @greeter.greet
end
Then /^I should see "([^"]*)"$/ do | greeting |
@message.should == greeting
end
module Codebreaker
class Marker
def initialize( secret, guess )
@secret, @guess = secret, guess
end
def number_match_count
total_match_count - exact_match_count
end
def exact_match_count
( 0..3 ).inject( 0 ) do | count, index |
count + ( exact_match?( index ) ? 1 : 0 )
end
end
private
def total_match_count
secret = @secret.split( '' )
@guess.split( '' ).inject( 0 ) do | count, n |
count + ( delete_first( secret, n ) ? 1 : 0 )
end
end
def delete_first( code, n )
code.delete_at( code.index( n ) ) if code.index( n )
end
def exact_match?( index )
@secret[ index ] == @guess[ index ]
end
def number_match?( index )
@secret.include?( @guess[ index ] ) &&
!exact_match?( index )
end
end
end
require_relative './spec_helper'
module Codebreaker
describe Marker do
describe "#exact_match_count" do
context "with no matches" do
it "returns 0" do
marker = Marker.new( '1234', '5555' )
marker.exact_match_count.should == 0
end
end
context "with 1 exact match" do
it "returns 1" do
marker = Marker.new( '1234', '1555' )
marker.exact_match_count.should == 1
end
end
context "with 1 number match" do
it "returns 0" do
marker = Marker.new( '1234', '2555' )
marker.exact_match_count.should == 0
end
end
context "with 1 exact match and 1 number match" do
it "returns 1" do
marker = Marker.new( '1234', '1525' )
marker.exact_match_count.should == 1
end
end
end
describe "#number_match_count" do
context "with no matches" do
it "returns 0" do
marker = Marker.new( '1234', '5555' )
marker.number_match_count.should == 0
end
end
context "with 1 number match" do
it "returns 1" do
marker = Marker.new( '1234', '2555' )
marker.number_match_count.should == 1
end
end
context "with 1 exact match" do
it "returns 0" do
marker = Marker.new( '1234', '1555' )
marker.number_match_count.should == 0
end
end
context "with 1 exact match and 1 number match" do
it "returns 1" do
marker = Marker.new( '1234', '1525' )
marker.number_match_count.should == 1
end
end
context "with 1 exact match duplicate in guess" do
it "returns 0" do
marker = Marker.new( '1234', '1155' )
marker.number_match_count.should == 0
end
end
end
end
end
require 'codebreaker'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment