Created
April 12, 2018 23:56
-
-
Save bhserna/882d5101bdaedcef732a0d078ce4f07e to your computer and use it in GitHub Desktop.
Example of Test contravariance
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "rspec" | |
module TicTacToe | |
def self.start_game | |
Game.new | |
end | |
class Game | |
def initialize | |
@board = Board.new | |
end | |
def players | |
["x", "o"] | |
end | |
def write(player, opts = {}) | |
handle_turn_for(player) do | |
board.write(player, opts) | |
end | |
end | |
def get_board | |
board.to_a | |
end | |
def has_winner? | |
!winner.nil? | |
end | |
def winner | |
players.find { |player| is_winner?(player) } | |
end | |
private | |
attr_reader :board | |
def is_winner?(player) | |
board.row_for?(player) || | |
board.column_for?(player) || | |
board.diagonal_for?(player) | |
end | |
def handle_turn_for(player) | |
raise "Not your turn" if player == @last_player | |
@last_player = player | |
yield | |
end | |
class Board | |
def initialize | |
@board = empty_board | |
end | |
def write(mark, opts) | |
index = opts.fetch(:in) | |
raise "Taken" unless board[index].empty? | |
self.board[index] = mark | |
end | |
def to_a | |
board | |
end | |
def row_for?(mark) | |
rows.any? { |row| row.all? { |content| content == mark } } | |
end | |
def column_for?(mark) | |
(0..2).any? { |column| rows.all? { |row| row[column] == mark } } | |
end | |
def diagonal_for?(mark) | |
[[0, 4, 8], [2, 4, 6]].any? do |diagonal| | |
diagonal.all? { |position| board[position] == mark } | |
end | |
end | |
protected | |
attr_reader :board | |
def rows | |
board.each_slice(3) | |
end | |
def empty_board | |
["", "", "", | |
"", "", "", | |
"", "", ""] | |
end | |
end | |
end | |
end | |
describe TicTacToe do | |
def start_game | |
game = TicTacToe.start_game | |
end | |
it "has two players" do | |
game = start_game | |
expect(game.players).to eq ["x", "o"] | |
end | |
it "starts with an empty board" do | |
game = start_game | |
expect(game.get_board).to eq [ | |
"", "", "", | |
"", "", "", | |
"", "", "" | |
] | |
end | |
it "can't write on an occupied position" do | |
game = start_game | |
game.write "x", in: 0 | |
expect { game.write "o", in: 0 }.to raise_error /Taken/ | |
end | |
it "can't write the same player twice" do | |
game = start_game | |
game.write "x", in: 0 | |
expect { game.write "x", in: 0 }.to raise_error /Not your turn/ | |
end | |
example "first stage" do | |
game = start_game | |
game.write "x", in: 0 | |
expect(game.get_board).to eq [ | |
"x", "", "", | |
"" , "", "", | |
"" , "", "" | |
] | |
game.write "o", in: 4 | |
expect(game.get_board).to eq [ | |
"x", "" , "", | |
"" , "o", "", | |
"" , "" , "" | |
] | |
expect(game).not_to have_winner | |
end | |
example "second stage" do | |
game = start_game | |
game.write "x", in: 0 | |
game.write "o", in: 4 | |
game.write "x", in: 2 | |
expect(game.get_board).to eq [ | |
"x", "" , "x", | |
"" , "o", "" , | |
"" , "" , "" | |
] | |
game.write "o", in: 5 | |
expect(game.get_board).to eq [ | |
"x", "" , "x", | |
"" , "o", "o" , | |
"" , "" , "" | |
] | |
expect(game).not_to have_winner | |
end | |
describe "winner in the top row" do | |
example do | |
game = start_game | |
game.write "x", in: 0 | |
game.write "o", in: 4 | |
game.write "x", in: 2 | |
game.write "o", in: 5 | |
game.write "x", in: 1 | |
expect(game.get_board).to eq [ | |
"x", "x", "x", | |
"" , "o", "o" , | |
"" , "" , "" | |
] | |
expect(game).to have_winner | |
expect(game.winner).to eq "x" | |
end | |
example do | |
game = start_game | |
game.write "o", in: 0 | |
game.write "x", in: 4 | |
game.write "o", in: 2 | |
game.write "x", in: 5 | |
game.write "o", in: 1 | |
expect(game.get_board).to eq [ | |
"o", "o", "o", | |
"" , "x", "x" , | |
"" , "" , "" | |
] | |
expect(game).to have_winner | |
expect(game.winner).to eq "o" | |
end | |
end | |
example "winner in the middle row" do | |
game = start_game | |
game.write "x", in: 0 | |
game.write "o", in: 4 | |
game.write "x", in: 2 | |
game.write "o", in: 5 | |
game.write "x", in: 8 | |
game.write "o", in: 3 | |
expect(game.get_board).to eq [ | |
"x", "" , "x", | |
"o", "o", "o", | |
"" , "" , "x" | |
] | |
expect(game).to have_winner | |
expect(game.winner).to eq "o" | |
end | |
example "winner in the last row" do | |
game = start_game | |
game.write "x", in: 0 | |
game.write "o", in: 6 | |
game.write "x", in: 2 | |
game.write "o", in: 7 | |
game.write "x", in: 4 | |
game.write "o", in: 8 | |
expect(game.get_board).to eq [ | |
"x", "" , "x", | |
"" , "x", "" , | |
"o", "o", "o" | |
] | |
expect(game).to have_winner | |
expect(game.winner).to eq "o" | |
end | |
example "winner in the first column" do | |
game = start_game | |
game.write "x", in: 0 | |
game.write "o", in: 2 | |
game.write "x", in: 3 | |
game.write "o", in: 7 | |
game.write "x", in: 6 | |
expect(game.get_board).to eq [ | |
"x", "" , "o", | |
"x" ,"" , "", | |
"x", "o", "" | |
] | |
expect(game).to have_winner | |
expect(game.winner).to eq "x" | |
end | |
example "winner in the second column" do | |
game = start_game | |
game.write "x", in: 1 | |
game.write "o", in: 2 | |
game.write "x", in: 4 | |
game.write "o", in: 8 | |
game.write "x", in: 7 | |
expect(game.get_board).to eq [ | |
"", "x", "o", | |
"", "x", "" , | |
"", "x", "o" | |
] | |
expect(game).to have_winner | |
expect(game.winner).to eq "x" | |
end | |
example "winner in the third column" do | |
game = start_game | |
game.write "x", in: 1 | |
game.write "o", in: 2 | |
game.write "x", in: 4 | |
game.write "o", in: 8 | |
game.write "x", in: 6 | |
game.write "o", in: 5 | |
expect(game.get_board).to eq [ | |
"" , "x", "o", | |
"" , "x", "o", | |
"x", "" , "o" | |
] | |
expect(game).to have_winner | |
expect(game.winner).to eq "o" | |
end | |
example "winner in diagonal" do | |
game = start_game | |
game.write "x", in: 0 | |
game.write "o", in: 2 | |
game.write "x", in: 4 | |
game.write "o", in: 5 | |
game.write "x", in: 8 | |
expect(game.get_board).to eq [ | |
"x", "" , "o", | |
"" , "x", "o", | |
"" , "" , "x" | |
] | |
expect(game).to have_winner | |
expect(game.winner).to eq "x" | |
end | |
example "winner in diagonal (other)" do | |
game = start_game | |
game.write "x", in: 2 | |
game.write "o", in: 0 | |
game.write "x", in: 4 | |
game.write "o", in: 5 | |
game.write "x", in: 6 | |
expect(game.get_board).to eq [ | |
"o", "" , "x", | |
"" , "x", "o", | |
"x", "" , "" | |
] | |
expect(game).to have_winner | |
expect(game.winner).to eq "x" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment