- Revision
- 881
- Author
- sirenian
- Date
- 2008-07-28 14:31:08 -0500 (Mon, 28 Jul 2008)
Log Message
[Liz] Multiple scenarios in the same file work independently; noughtsandcrosses provides examples (but not in build yet)
Modified Paths
- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/ScenarioBehaviour.java
- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/ScenarioRunnerBehaviour.java
- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/PatternStepParserBehaviour.java
- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/ScenarioFileLoaderBehaviour.java
- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/StepResultBehaviour.java
- trunk/jbehave-core/src/java/org/jbehave/scenario/Scenario.java
- trunk/jbehave-core/src/java/org/jbehave/scenario/ScenarioRunner.java
- trunk/jbehave-core/src/java/org/jbehave/scenario/parser/PatternStepParser.java
- trunk/jbehave-core/src/java/org/jbehave/scenario/parser/ScenarioDefiner.java
- trunk/jbehave-core/src/java/org/jbehave/scenario/parser/ScenarioFileLoader.java
Added Paths
- trunk/examples/noughtsandcrosses/
- trunk/examples/noughtsandcrosses/lib/
- trunk/examples/noughtsandcrosses/lib/tyburn-0.1.jar
- trunk/examples/noughtsandcrosses/src/
- trunk/examples/noughtsandcrosses/src/behaviour/
- trunk/examples/noughtsandcrosses/src/behaviour/com/
- trunk/examples/noughtsandcrosses/src/behaviour/com/lunivore/
- trunk/examples/noughtsandcrosses/src/behaviour/com/lunivore/noughtsandcrosses/
- trunk/examples/noughtsandcrosses/src/behaviour/com/lunivore/noughtsandcrosses/game/
- trunk/examples/noughtsandcrosses/src/behaviour/com/lunivore/noughtsandcrosses/game/GameModelBehaviour.java
- trunk/examples/noughtsandcrosses/src/behaviour/com/lunivore/noughtsandcrosses/game/WinningScenarioBehaviour.java
- trunk/examples/noughtsandcrosses/src/java/
- trunk/examples/noughtsandcrosses/src/java/com/
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/NoughtsAndCrosses.java
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/Coord.java
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/Game.java
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/GameModel.java
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/GameObserver.java
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/Player.java
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/WinningScenario.java
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/ComponentNames.java
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/GridPanel.java
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/MessageLabel.java
- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/NoughtsAndCrossesFrame.java
- trunk/examples/noughtsandcrosses/src/scenario/
- trunk/examples/noughtsandcrosses/src/scenario/com/
- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/
- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/
- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/PlayersCanTakeTurns.java
- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/TheGridStartsEmpty.java
- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/ThreeInARowWins.java
- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/players_can_take_turns
- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/steps/
- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/steps/GridSteps.java
- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/the_grid_starts_empty
- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/three_in_a_row_wins
- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/scenarios/MyMultipleScenario.java
- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/scenarios/my_multiple_scenario
Diff
Added: trunk/examples/noughtsandcrosses/lib/tyburn-0.1.jar
(Binary files differ)
Added: trunk/examples/noughtsandcrosses/src/behaviour/com/lunivore/noughtsandcrosses/game/GameModelBehaviour.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/behaviour/com/lunivore/noughtsandcrosses/game/GameModelBehaviour.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/behaviour/com/lunivore/noughtsandcrosses/game/GameModelBehaviour.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,79 @@ +package com.lunivore.noughtsandcrosses.game; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.jbehave.Ensure.ensureThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.junit.Test; + + + +public class GameModelBehaviour { + + @Test + public void shouldStartEmptyAndTellObserver() { + GameModel game = new GameModel(); + GameObserver observer = mock(GameObserver.class); + game.addObserver(observer); + + verify(observer).gameChanged(game); + + for (int row = 0; row < 3; row++) { + for (int column = 0; column < 3; column++) { + ensureThat(game.playerAt(column, row), equalTo(Player.NONE)); + } + } + } + + @Test + public void shouldPlaceTokenForCurrentPlayerInTheGivenColumnAndRowStartingWithX() { + GameModel game = new GameModel(); + GameObserver observer = mock(GameObserver.class); + game.addObserver(observer); + + game.playerActsAt(0, 1); + game.playerActsAt(0, 2); + + verify(observer, times(3)).gameChanged(game); + + ensureThat(game.playerAt(0, 0), equalTo(Player.NONE)); + ensureThat(game.playerAt(0, 1), equalTo(Player.X)); + ensureThat(game.playerAt(0, 2), equalTo(Player.O)); + } + + @Test + public void shouldNotifyObserverWhenTheCurrentPlayerWins() { + // Given a game which X is about to win + GameModel game = new GameModel(); + game.playerActsAt(0, 0); + game.playerActsAt(1, 0); + game.playerActsAt(0, 1); + game.playerActsAt(2, 0); + + + MyGameObserver observer = new MyGameObserver(); + game.addObserver(observer); + + // When X wins the game + game.playerActsAt(0, 2); + + // Then we should see X is the current player and the game is over + ensureThat(observer.game.currentPlayer(), equalTo(Player.X)); + } + + private static class MyGameObserver implements GameObserver { + + private Game game; + + public void gameChanged(Game game) { + } + + public void gameWon(Game game) { + this.game = game; + } + + } + +}
Added: trunk/examples/noughtsandcrosses/src/behaviour/com/lunivore/noughtsandcrosses/game/WinningScenarioBehaviour.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/behaviour/com/lunivore/noughtsandcrosses/game/WinningScenarioBehaviour.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/behaviour/com/lunivore/noughtsandcrosses/game/WinningScenarioBehaviour.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,26 @@ +package com.lunivore.noughtsandcrosses.game; + +import static org.jbehave.Ensure.ensureThat; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + + +public class WinningScenarioBehaviour { + + @Test + public void shouldFindWinningGameWhenCoordsAreAllTheSamePlayer() { + Map<Coord, Player> game = new HashMap<Coord, Player>(); + game.put(new Coord(0,0), Player.X); + game.put(new Coord(1,0), Player.X); + game.put(new Coord(1,1), Player.O); + game.put(new Coord(2,2), Player.O); + ensureThat(!WinningScenario.ROW1.isAchievedIn(game)); + game.put(new Coord(2,0), Player.X); + ensureThat(WinningScenario.ROW1.isAchievedIn(game)); + ensureThat(!WinningScenario.COL1.isAchievedIn(game)); + ensureThat(!WinningScenario.NORTH_WEST.isAchievedIn(game)); + } +}
Added: trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/NoughtsAndCrosses.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/NoughtsAndCrosses.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/NoughtsAndCrosses.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,15 @@ +package com.lunivore.noughtsandcrosses; + +import com.lunivore.noughtsandcrosses.game.GameModel; +import com.lunivore.noughtsandcrosses.view.NoughtsAndCrossesFrame; + +public class NoughtsAndCrosses { + + public NoughtsAndCrosses() { + new NoughtsAndCrossesFrame(new GameModel()); + } + + public static void main(String[] args) { + new NoughtsAndCrosses(); + } +}
Added: trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/Coord.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/Coord.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/Coord.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,29 @@ +/** + * + */ +package com.lunivore.noughtsandcrosses.game; + +class Coord { + private final int column; + private final int row; + + public Coord(int column, int row) { + this.column = column; + this.row = row; + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + column; + result = 31 * result + row; + return result; + } + + @Override + public boolean equals(Object obj) { + final Coord other = (Coord) obj; + return column == other.column && row == other.row; + } + +} \ No newline at end of file
Added: trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/Game.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/Game.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/Game.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,13 @@ +package com.lunivore.noughtsandcrosses.game; + + +public interface Game { + + public void addObserver(GameObserver observer); + + public void playerActsAt(int row, int column); + + public Player playerAt(int column, int row); + + public Player currentPlayer(); +}
Added: trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/GameModel.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/GameModel.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/GameModel.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,62 @@ +package com.lunivore.noughtsandcrosses.game; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class GameModel implements Game { + + private Map<Coord, Player> map = new HashMap<Coord, Player>(); + private Player currentPlayer = Player.X; + private List<GameObserver> observers = new ArrayList<GameObserver>(); + + public void addObserver(GameObserver observer) { + observers.add(observer); + observer.gameChanged(this); + } + + public void playerActsAt(int column, int row) { + map.put(new Coord(column, row), currentPlayer); + if (gameWon()) { + notifyObserversGameWon(); + } else { + nextPlayer(); + notifyObserversGameChanged(); + } + } + + private void notifyObserversGameWon() { + for (GameObserver observer : observers) { + observer.gameWon(this); + } + } + + private boolean gameWon() { + for (WinningScenario scenario : WinningScenario.values()) { + if(scenario.isAchievedIn(map)) { + return true; + } + } + return false; + } + + private void notifyObserversGameChanged() { + for (GameObserver observer : observers) { + observer.gameChanged(this); + } + } + + private void nextPlayer() { + currentPlayer = currentPlayer == Player.X ? Player.O : Player.X; + } + + public Player playerAt(int column, int row) { + Player player = map.get(new Coord(column, row)); + return player == null ? Player.NONE : player; + } + + public Player currentPlayer() { + return currentPlayer; + } +}
Added: trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/GameObserver.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/GameObserver.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/GameObserver.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,8 @@ +package com.lunivore.noughtsandcrosses.game; + +public interface GameObserver { + + void gameChanged(Game game); + + void gameWon(Game game); +}
Added: trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/Player.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/Player.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/Player.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,16 @@ +package com.lunivore.noughtsandcrosses.game; + +public enum Player { + + O("O"), X("X"), NONE(""); + + private final String rendered; + + private Player(String rendered) { + this.rendered = rendered; + } + + public String asString() { + return rendered; + } +}
Added: trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/WinningScenario.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/WinningScenario.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/game/WinningScenario.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,36 @@ +package com.lunivore.noughtsandcrosses.game; + +import java.util.Map; + + +public enum WinningScenario { + ROW1(new Coord(0, 0), new Coord(1, 0), new Coord(2, 0)), + ROW2(new Coord(0, 1), new Coord(1, 1), new Coord(2, 1)), + ROW3(new Coord(0, 2), new Coord(1, 2), new Coord(2, 2)), + COL1(new Coord(0, 0), new Coord(0, 1), new Coord(0, 2)), + COL2(new Coord(1, 0), new Coord(1, 1), new Coord(1, 2)), + COL3(new Coord(2, 0), new Coord(2, 1), new Coord(2, 2)), + NORTH_WEST(new Coord(0, 0), new Coord(1, 1), new Coord(2, 2)), + NORTH_EAST(new Coord(2, 0), new Coord(1, 1), new Coord(0, 2)); + + private final Coord[] coords; + + private WinningScenario(Coord... coords) { + this.coords = coords; + } + + public boolean isAchievedIn(Map<Coord, Player> map) { + Player candidate = null; + for (Coord coord : coords) { + if (map.get(coord) == null) { + return false; + } else if (candidate == null){ + candidate = map.get(coord); + } else if (candidate != map.get(coord)){ + return false; + } + } + return true; + } + +}
Added: trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/ComponentNames.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/ComponentNames.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/ComponentNames.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,9 @@ +package com.lunivore.noughtsandcrosses.view; + +public class ComponentNames { + + public static final String NOUGHTSANDCROSSES = "noughtsandcrosses"; + public static final String MESSAGE = "message"; + public static String GRID = "grid"; + +}
Added: trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/GridPanel.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/GridPanel.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/GridPanel.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,81 @@ +package com.lunivore.noughtsandcrosses.view; + +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JPanel; + +import com.lunivore.noughtsandcrosses.game.Game; +import com.lunivore.noughtsandcrosses.game.GameObserver; + [EMAIL PROTECTED]("serial") +public class GridPanel extends JPanel implements GameObserver { + public static class OXButton extends JButton { + private final int row; + private final int column; + + public OXButton(String string, int row, int column) { + this.row = row; + this.column = column; + setPreferredSize(new Dimension(50, 50)); + setName(string); + } + } + + private static final String NL = System.getProperty("line.separator"); + + private OXButton[][] gridButtons = new OXButton[][] { + new OXButton[] {new OXButton("a1", 0, 0), new OXButton("a2", 0, 1), new OXButton("a3", 0, 2)}, + new OXButton[] {new OXButton("b1", 1, 0), new OXButton("b2", 1, 1), new OXButton("b3", 1, 2)}, + new OXButton[] {new OXButton("c1", 2, 0), new OXButton("c2", 2, 1), new OXButton("c3", 2, 2)} + }; + + public GridPanel(final Game game) { + setName(ComponentNames.GRID); + setLayout(new GridLayout(3, 3)); + + for (OXButton[] row : gridButtons) { + for (final OXButton button : row) { + add(button); + button.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e) { + game.playerActsAt(button.column, button.row); + } + }); + } + } + + game.addObserver(this); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + for (int row = 0; row < gridButtons.length; row++) { + for (OXButton button : gridButtons[row]) { + builder.append(text(button)); + } + if (row < gridButtons.length - 1) { builder.append(NL); } + } + return builder.toString(); + } + + private String text(JButton button) { + return button.getText() == "" ? "." : button.getText(); + } + + public void gameChanged(Game game) { + for (OXButton[] row : gridButtons) { + for (OXButton button : row) { + button.setText(game.playerAt(button.column, button.row).asString()); + } + } + } + + public void gameWon(Game game) { + gameChanged(game); + } +}
Added: trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/MessageLabel.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/MessageLabel.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/MessageLabel.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,27 @@ +package com.lunivore.noughtsandcrosses.view; + +import java.awt.Dimension; + +import javax.swing.JLabel; + +import com.lunivore.noughtsandcrosses.game.Game; +import com.lunivore.noughtsandcrosses.game.GameObserver; + [EMAIL PROTECTED]("serial") +public class MessageLabel extends JLabel implements GameObserver { + + public MessageLabel(Game game) { + setName(ComponentNames.MESSAGE); + setText("X's turn"); + setPreferredSize(new Dimension(150, 50)); + game.addObserver(this); + } + + public void gameChanged(Game game) { + setText(game.currentPlayer().asString() + "'s turn"); + } + + public void gameWon(Game game) { + setText(game.currentPlayer().asString() + " wins!"); + } +}
Added: trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/NoughtsAndCrossesFrame.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/NoughtsAndCrossesFrame.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/java/com/lunivore/noughtsandcrosses/view/NoughtsAndCrossesFrame.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,24 @@ +package com.lunivore.noughtsandcrosses.view; + +import java.awt.BorderLayout; + +import javax.swing.JFrame; +import javax.swing.WindowConstants; + +import com.lunivore.noughtsandcrosses.game.Game; + [EMAIL PROTECTED]("serial") +public class NoughtsAndCrossesFrame extends JFrame { + + public NoughtsAndCrossesFrame(Game game) { + setName(ComponentNames.NOUGHTSANDCROSSES); + + this.getContentPane().setLayout(new BorderLayout()); + this.getContentPane().add(new GridPanel(game), BorderLayout.NORTH); + this.getContentPane().add(new MessageLabel(game), BorderLayout.CENTER); + + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + pack(); + setVisible(true); + } +}
Added: trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/PlayersCanTakeTurns.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/PlayersCanTakeTurns.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/PlayersCanTakeTurns.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,13 @@ +package com.lunivore.noughtsandcrosses; + +import org.jbehave.scenario.Scenario; + +import com.lunivore.noughtsandcrosses.steps.GridSteps; + +public class PlayersCanTakeTurns extends Scenario { + + public PlayersCanTakeTurns() { + super(new GridSteps()); + } + +}
Added: trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/TheGridStartsEmpty.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/TheGridStartsEmpty.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/TheGridStartsEmpty.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,12 @@ +package com.lunivore.noughtsandcrosses; + +import org.jbehave.scenario.Scenario; + +import com.lunivore.noughtsandcrosses.steps.GridSteps; + + +public class TheGridStartsEmpty extends Scenario { + public TheGridStartsEmpty() { + super(new GridSteps()); + } +}
Added: trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/ThreeInARowWins.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/ThreeInARowWins.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/ThreeInARowWins.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,13 @@ +package com.lunivore.noughtsandcrosses; + +import org.jbehave.scenario.Scenario; + +import com.lunivore.noughtsandcrosses.steps.GridSteps; + +public class ThreeInARowWins extends Scenario { + + public ThreeInARowWins() { + super(new GridSteps()); + } + +}
Added: trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/players_can_take_turns (0 => 881)
--- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/players_can_take_turns (rev 0) +++ trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/players_can_take_turns 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,20 @@ +Scenario: X takes a turn + +Given the game is running +When the player clicks a1 +Then the grid should look like +X.. +... +... + +Scenario: O takes a turn + +Given a grid that looks like +X.. +... +... +When the player clicks a2 +Then the grid should look like +XO. +... +...
Added: trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/steps/GridSteps.java (0 => 881)
--- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/steps/GridSteps.java (rev 0) +++ trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/steps/GridSteps.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,83 @@ +package com.lunivore.noughtsandcrosses.steps; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.jbehave.Ensure.ensureThat; + +import java.awt.Component; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.swing.JLabel; + +import org.jbehave.scenario.annotations.Given; +import org.jbehave.scenario.annotations.Then; +import org.jbehave.scenario.annotations.When; +import org.jbehave.scenario.steps.Steps; +import org.lunivore.tyburn.WindowControl; + +import com.lunivore.noughtsandcrosses.NoughtsAndCrosses; +import com.lunivore.noughtsandcrosses.view.ComponentNames; + +public class GridSteps extends Steps { + + public static String ROWS = "abc"; + public static String COLUMNS = "123"; + protected static final String NL = System.getProperty("line.separator"); + protected WindowControl windowControl; + + @Given("the game is running") + public void givenTheGameIsRunning() { + windowControl = new WindowControl(ComponentNames.NOUGHTSANDCROSSES); + new NoughtsAndCrosses(); + } + + @Given("a grid that looks like $grid") + public void givenThatTheGridLooksLike(String grid) throws Exception { + givenTheGameIsRunning(); + ArrayList<String> oTurns = new ArrayList<String>(); + ArrayList<String> xTurns = new ArrayList<String>(); + + captureMoves(oTurns, xTurns, grid); + performMoves(oTurns, xTurns); + } + + @Then("the message should read \"$message\"") + public void thenTheMessageShouldRead(String message) throws Exception { + JLabel messageLabel = (JLabel) windowControl.findComponent(ComponentNames.MESSAGE); + ensureThat(messageLabel.getText(), equalTo(message)); + } + + @Then("the grid should look like $grid") + public void thenTheGridShouldLookLike(String grid) throws Exception { + Component gridPanel = windowControl.findComponent(ComponentNames.GRID); + ensureThat(gridPanel.toString(), equalTo(grid)); + } + + @When("the player clicks $space") + public void whenPlayerClicksInSpace(String space) throws Exception { + windowControl.clickButton(space); + } + + private void performMoves(List<String> oTurns, List<String> xTurns) throws Exception { + while (xTurns.size() > 0) { + whenPlayerClicksInSpace(xTurns.remove(0)); + if (oTurns.size() >0) { + whenPlayerClicksInSpace(oTurns.remove(0)); + } + } + } + + private void captureMoves(List<String> oTurns, List<String> xTurns, String grid) { + + List<String> lines = Arrays.asList(grid.split(NL)); + for(int row=0;row<3;row++) { + for(int col=0;col<3;col++) { + char player = lines.get(row).charAt(col); + String spaceLabel = "" + ROWS.charAt(row) + COLUMNS.charAt(col); + if(player == 'O') {oTurns.add(spaceLabel);} + if(player == 'X') {xTurns.add(spaceLabel);} + } + } + } +}
Added: trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/the_grid_starts_empty (0 => 881)
--- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/the_grid_starts_empty (rev 0) +++ trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/the_grid_starts_empty 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,6 @@ +Given the game is running +Then the grid should look like +... +... +... +Then the message should read "X's turn" \ No newline at end of file
Added: trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/three_in_a_row_wins (0 => 881)
--- trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/three_in_a_row_wins (rev 0) +++ trunk/examples/noughtsandcrosses/src/scenario/com/lunivore/noughtsandcrosses/three_in_a_row_wins 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,10 @@ +Given the grid looks like +OO. +XX. +X.. +When the player clicks a3 +Then the grid should look like +OOO +XX. +X.. +Then the message should read "O wins!" \ No newline at end of file
Modified: trunk/jbehave-core/src/behaviour/org/jbehave/scenario/ScenarioBehaviour.java (880 => 881)
--- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/ScenarioBehaviour.java 2008-07-27 21:53:10 UTC (rev 880) +++ trunk/jbehave-core/src/behaviour/org/jbehave/scenario/ScenarioBehaviour.java 2008-07-28 19:31:08 UTC (rev 881) @@ -42,7 +42,8 @@ PrintStreamScenarioReporter reporter = new PrintStreamScenarioReporter(new PrintStream(output)); MySteps steps = new MySteps(); - stub(fileLoader.loadStepsFor(MyScenario.class)).toReturn(new ScenarioDefinition(stepParser, "my_scenario")); + stub(fileLoader.loadStepsFor(MyScenario.class)).toReturn(Arrays.asList( + new ScenarioDefinition(stepParser, "my_scenario"))); stub(stepParser.findSteps("my_scenario")).toReturn(Arrays.asList(new String[] { "Given I have 2 cows", "When I leave them over the winter", @@ -66,7 +67,8 @@ ScenarioReporter reporter = new BufferScenarioReporter(buffer); MySteps steps = new MySteps(); - stub(fileLoader.loadStepsFor(MyScenario.class)).toReturn(new ScenarioDefinition(stepParser, "my_scenario")); + stub(fileLoader.loadStepsFor(MyScenario.class)).toReturn(Arrays.asList( + new ScenarioDefinition(stepParser, "my_scenario"))); stub(stepParser.findSteps("my_scenario")).toReturn(Arrays.asList(new String[] { "Given I have 2 cows", "When I leave them over the winter", @@ -95,7 +97,8 @@ ScenarioReporter reporter = new PrintStreamScenarioReporter(new PrintStream(output)); MySteps steps = new MySteps(); - stub(scenarioDefiner.loadStepsFor(MyScenario.class)).toReturn(new ScenarioDefinition(stepParser, "my_scenario")); + stub(scenarioDefiner.loadStepsFor(MyScenario.class)).toReturn(Arrays.asList( + new ScenarioDefinition(stepParser, "my_scenario"))); stub(stepParser.findSteps("my_scenario")).toReturn(Arrays.asList(new String[] { "Given I have 2 cows", "When I put them in a field",
Modified: trunk/jbehave-core/src/behaviour/org/jbehave/scenario/ScenarioRunnerBehaviour.java (880 => 881)
--- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/ScenarioRunnerBehaviour.java 2008-07-27 21:53:10 UTC (rev 880) +++ trunk/jbehave-core/src/behaviour/org/jbehave/scenario/ScenarioRunnerBehaviour.java 2008-07-28 19:31:08 UTC (rev 881) @@ -5,6 +5,7 @@ import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.stub; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import org.jbehave.scenario.steps.Step; @@ -104,4 +105,23 @@ } + @Test + public void shouldResetStateForEachSetOfSteps() throws Throwable { + + ScenarioReporter reporter = mock(ScenarioReporter.class); + Step pendingStep = mock(Step.class); + Step secondStep = mock(Step.class); + stub(pendingStep.perform()).toReturn(StepResult.pending("pendingStep")); + stub(secondStep.perform()).toReturn(StepResult.success("secondStep")); + + ScenarioRunner runner = new ScenarioRunner(reporter); + + runner.run(pendingStep); + runner.run(secondStep); // should reset state for this one + + verify(pendingStep).perform(); + verify(secondStep).perform(); + verify(secondStep, never()).doNotPerform(); + } + }
Modified: trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/PatternStepParserBehaviour.java (880 => 881)
--- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/PatternStepParserBehaviour.java 2008-07-27 21:53:10 UTC (rev 880) +++ trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/PatternStepParserBehaviour.java 2008-07-28 19:31:08 UTC (rev 881) @@ -5,7 +5,6 @@ import java.util.List; -import org.jbehave.scenario.parser.PatternStepParser; import org.junit.Test;
Modified: trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/ScenarioFileLoaderBehaviour.java (880 => 881)
--- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/ScenarioFileLoaderBehaviour.java 2008-07-27 21:53:10 UTC (rev 880) +++ trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/ScenarioFileLoaderBehaviour.java 2008-07-28 19:31:08 UTC (rev 881) @@ -8,17 +8,20 @@ import java.util.List; import org.jbehave.scenario.Scenario; +import org.jbehave.scenario.parser.scenarios.MyMultipleScenario; import org.jbehave.scenario.parser.scenarios.MyPendingScenario; import org.junit.Test; public class ScenarioFileLoaderBehaviour { - @Test + private static final String NL = System.getProperty("line.separator"); + + @Test public void canLoadScenario() { StepParser parser = mock(StepParser.class); ScenarioFileLoader loader = new ScenarioFileLoader(parser); - ScenarioDefinition definition = loader.loadStepsFor(MyPendingScenario.class); - definition.getSteps(); + List<ScenarioDefinition> definitions = loader.loadStepsFor(MyPendingScenario.class); + definitions.get(0).getSteps(); verify(parser).findSteps("Given my scenario"); } @@ -26,7 +29,7 @@ public void canLoadScenarioWithCustomFilenameResolver() { StepParser parser = mock(StepParser.class); ScenarioFileLoader loader = new ScenarioFileLoader(new CasePreservingResolver(".scenario"), parser); - loader.loadStepsFor(MyPendingScenario.class).getSteps(); + loader.loadStepsFor(MyPendingScenario.class).get(0).getSteps(); verify(parser).findSteps("Given my scenario"); } @@ -41,6 +44,15 @@ ScenarioFileLoader loader = new ScenarioFileLoader(new InvalidClassLoader()); loader.loadStepsFor(MyPendingScenario.class); } + + @Test + public void canLoadMultipleScenariosInTheSameFile() { + StepParser parser = mock(StepParser.class); + ScenarioFileLoader loader = new ScenarioFileLoader(parser); + List<ScenarioDefinition> definitions = loader.loadStepsFor(MyMultipleScenario.class); + definitions.get(1).getSteps(); + verify(parser).findSteps("Scenario: the second scenario" + NL + NL + "Given my second scenario"); + } static class InexistentScenario extends Scenario {
Added: trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/scenarios/MyMultipleScenario.java (0 => 881)
--- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/scenarios/MyMultipleScenario.java (rev 0) +++ trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/scenarios/MyMultipleScenario.java 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,20 @@ +package org.jbehave.scenario.parser.scenarios; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.jbehave.OurTechnique; +import org.jbehave.scenario.Scenario; +import org.jbehave.scenario.reporters.PrintStreamScenarioReporter; + +public class MyMultipleScenario extends Scenario { + public MyMultipleScenario() { + // Making sure this doesn't output to the build while it's running + super(new OurTechnique() { + @Override + public PrintStreamScenarioReporter forReportingScenarios() { + return new PrintStreamScenarioReporter(new PrintStream(new ByteArrayOutputStream())); + } + }); + } +}
Added: trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/scenarios/my_multiple_scenario (0 => 881)
--- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/scenarios/my_multiple_scenario (rev 0) +++ trunk/jbehave-core/src/behaviour/org/jbehave/scenario/parser/scenarios/my_multiple_scenario 2008-07-28 19:31:08 UTC (rev 881) @@ -0,0 +1,7 @@ +Scenario: the first scenario + +Given my scenario + +Scenario: the second scenario + +Given my second scenario \ No newline at end of file
Modified: trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/StepResultBehaviour.java (880 => 881)
--- trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/StepResultBehaviour.java 2008-07-27 21:53:10 UTC (rev 880) +++ trunk/jbehave-core/src/behaviour/org/jbehave/scenario/steps/StepResultBehaviour.java 2008-07-28 19:31:08 UTC (rev 881) @@ -1,11 +1,10 @@ package org.jbehave.scenario.steps; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - import static org.jbehave.Ensure.ensureThat; import static org.jbehave.Ensure.not; import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import org.jbehave.scenario.ScenarioReporter; import org.junit.Test;
Modified: trunk/jbehave-core/src/java/org/jbehave/scenario/Scenario.java (880 => 881)
--- trunk/jbehave-core/src/java/org/jbehave/scenario/Scenario.java 2008-07-27 21:53:10 UTC (rev 880) +++ trunk/jbehave-core/src/java/org/jbehave/scenario/Scenario.java 2008-07-28 19:31:08 UTC (rev 881) @@ -39,9 +39,11 @@ @Test public void runUsingSteps() throws Throwable { - ScenarioDefinition definition = scenarioDefiner.loadStepsFor(this.getClass()); - Step[] steps = createRealStepsFromCandidates(definition.getSteps()); - scenarioRunner.run(steps); + List<ScenarioDefinition> definitions = scenarioDefiner.loadStepsFor(this.getClass()); + for (ScenarioDefinition definition : definitions) { + Step[] steps = createRealStepsFromCandidates(definition.getSteps()); + scenarioRunner.run(steps); + } } private Step[] createRealStepsFromCandidates(List<String> stringSteps) {
Modified: trunk/jbehave-core/src/java/org/jbehave/scenario/ScenarioRunner.java (880 => 881)
--- trunk/jbehave-core/src/java/org/jbehave/scenario/ScenarioRunner.java 2008-07-27 21:53:10 UTC (rev 880) +++ trunk/jbehave-core/src/java/org/jbehave/scenario/ScenarioRunner.java 2008-07-28 19:31:08 UTC (rev 881) @@ -11,7 +11,7 @@ */ public class ScenarioRunner { - private State state = new FineSoFar(); + private State state; private final ScenarioReporter reporter; public ScenarioRunner(ScenarioReporter reporter) { @@ -19,6 +19,7 @@ } public void run(Step... steps) throws Throwable { + state = new FineSoFar(); for (Step step : steps) { state.run(step); }
Modified: trunk/jbehave-core/src/java/org/jbehave/scenario/parser/PatternStepParser.java (880 => 881)
--- trunk/jbehave-core/src/java/org/jbehave/scenario/parser/PatternStepParser.java 2008-07-27 21:53:10 UTC (rev 880) +++ trunk/jbehave-core/src/java/org/jbehave/scenario/parser/PatternStepParser.java 2008-07-28 19:31:08 UTC (rev 881) @@ -7,7 +7,7 @@ public class PatternStepParser implements StepParser { - public static final String DEFAULT_PARSE_REGEX = "((Given|When|Then) (.|\\s)*?)\\s*(\\Z|Given|When|Then)"; + public static final String DEFAULT_PARSE_REGEX = "((Given|When|Then) (.|\\s)*?)\\s*(\\Z|Given|When|Then|Scenario:)"; private final Pattern pattern;
Modified: trunk/jbehave-core/src/java/org/jbehave/scenario/parser/ScenarioDefiner.java (880 => 881)
--- trunk/jbehave-core/src/java/org/jbehave/scenario/parser/ScenarioDefiner.java 2008-07-27 21:53:10 UTC (rev 880) +++ trunk/jbehave-core/src/java/org/jbehave/scenario/parser/ScenarioDefiner.java 2008-07-28 19:31:08 UTC (rev 881) @@ -1,9 +1,11 @@ package org.jbehave.scenario.parser; +import java.util.List; + import org.jbehave.scenario.Scenario; public interface ScenarioDefiner { - ScenarioDefinition loadStepsFor(Class<? extends Scenario> clazz); + List<ScenarioDefinition> loadStepsFor(Class<? extends Scenario> clazz); } \ No newline at end of file
Modified: trunk/jbehave-core/src/java/org/jbehave/scenario/parser/ScenarioFileLoader.java (880 => 881)
--- trunk/jbehave-core/src/java/org/jbehave/scenario/parser/ScenarioFileLoader.java 2008-07-27 21:53:10 UTC (rev 880) +++ trunk/jbehave-core/src/java/org/jbehave/scenario/parser/ScenarioFileLoader.java 2008-07-28 19:31:08 UTC (rev 881) @@ -3,6 +3,10 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.jbehave.scenario.Scenario; @@ -43,20 +47,43 @@ return stream; } - public ScenarioDefinition loadStepsFor(Class<? extends Scenario> scenarioClass) { - return new ScenarioDefinition(stepParser, asString(loadStepsAsStreamFor(scenarioClass))); + public List<ScenarioDefinition>loadStepsFor(Class<? extends Scenario> scenarioClass) { + List<String> scenarios = asString(loadStepsAsStreamFor(scenarioClass)); + List<ScenarioDefinition> scenarioDefinitions = new ArrayList<ScenarioDefinition>(); + for (String string : scenarios) { + scenarioDefinitions.add(new ScenarioDefinition(stepParser, string)); + } + return scenarioDefinitions; } - private String asString(InputStream stream) { + private List<String> asString(InputStream stream) { try { byte[] bytes = new byte[stream.available()]; stream.read(bytes); ByteArrayOutputStream output = new ByteArrayOutputStream(); output.write(bytes); - return output.toString(); + String allScenariosInFile = output.toString(); + return splitScenarios(allScenariosInFile); } catch (IOException e) { throw new InvalidScenarioResourceException("Failed to convert scenario resouce to string", e); } } + private List<String> splitScenarios(String allScenariosInFile) { + Pattern scenarioSplitter = Pattern.compile("((Scenario:) (.|\\s)*?)\\s*(\\Z|Scenario:).*", Pattern.DOTALL); + Matcher matcher = scenarioSplitter.matcher(allScenariosInFile); + int startAt = 0; + List<String> scenarios = new ArrayList<String>(); + if (matcher.matches()) { + while(matcher.find(startAt)) { + scenarios.add(matcher.group(1)); + startAt = matcher.start(4); + } + } else { + String loneScenario = allScenariosInFile; + scenarios.add(loneScenario); + } + return scenarios; + } + }
To unsubscribe from this list please visit:
