├── .classpath
├── .gitignore
├── .project
├── .travis.yml
├── README.md
├── build.properties_sample
├── build.xml
├── ivy.xml
└── src
├── main
├── java
│ └── com
│ │ └── zsoltfabok
│ │ └── blog
│ │ ├── Munger.java
│ │ ├── SentenceHelper.java
│ │ ├── SimpleTextMunger.java
│ │ └── web
│ │ └── controller
│ │ └── MungerController.java
├── resources
│ └── applicationContext.xml
└── webapp
│ └── WEB-INF
│ ├── munger-servlet.xml
│ ├── views
│ └── index.jsp
│ └── web.xml
└── test
├── java
└── com
│ └── zsoltfabok
│ └── blog
│ ├── EmbeddedTomcat.java
│ ├── SimpleTextMungerStepsdef.java
│ ├── SimpleTextMunger_Test.java
│ ├── WebTextMungerStepsdef.java
│ ├── WebTextMunger_Test.java
│ └── spring
│ └── SimpleTextMungerTest.java
└── resources
├── cucumber.xml
├── log4j.properties
├── simple_text_munger.feature
└── web_text_munger.feature
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | >>>>>>> episode_3
11 | >>>>>>> episode_4
12 |
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | lib
2 | bin
3 | *.class
4 | .settings
5 | TEST-*
6 | TESTS-*
7 | build.properties
8 | target
9 | work
10 | tomcat.8080
11 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | blog.cucumberjvm
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 | org.apache.ivyde.eclipse.ivynature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | script: ant clean test
3 | # whitelist
4 | branches:
5 | only:
6 | - master
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This repository contains the java code I created while I was writing my posts about cucumber-jvm. Each post has its different branch:
2 |
3 | - **http://www.zsoltfabok.com/blog/2011/12/cucumber-jvm-preparation/** ([episode_1](https://github.com/ZsoltFabok/cucumber-jvm-post/tree/episode_1)): it is about the basics of BDD and cucumber and how to set up an eclipse project for executing cucumber features from java
4 | - **http://www.zsoltfabok.com/blog/2011/12/cucumber-jvm-more-scenarios/** ([episode_2](https://github.com/ZsoltFabok/cucumber-jvm-post/tree/episode_2)): the series continues with *scenarios* and with a couple of ideas on how to use them
5 | - **http://www.zsoltfabok.com/blog/2012/01/cucumber-jvm-di/** ([episode_3](https://github.com/ZsoltFabok/cucumber-jvm-post/tree/episode_3)): in this episode I'm introducing *Spring* and dependency injection
6 | - **http://zsoltfabok.com/blog/2012/03/cucumber-jvm-mocking/** ([episode_4](https://github.com/ZsoltFabok/cucumber-jvm-post/tree/episode_4)): there is testing without mocking. This episode shows how to use *mockito* with *cucumber-jvm*
7 | - **http://zsoltfabok.com/blog/2012/09/cucumber-jvm-web-with-spring-mvc/** ([episode_5](https://github.com/ZsoltFabok/cucumber-jvm-post/tree/episode_5)): a huge step forward: introducing MVC and full-stack testing
8 | - **http://zsoltfabok.com/blog/2012/09/cucumber-jvm-hooks/** ([episode_6](https://github.com/ZsoltFabok/cucumber-jvm-post/tree/episode_6)): I'm using hooks for the sake of cleaner test code
9 |
10 | ### Building, configuring and running
11 |
12 | I'm using [ivy](http://ant.apache.org/ivy/) for managing the project dependencies, so after cloning the repository you have to run ivy:
13 | ```bash
14 | % ivy
15 | ```
16 | and install the [ivyDE plugin](http://ant.apache.org/ivy/ivyde/index.html).
17 |
18 | Building the project:
19 | ```bash
20 | % ant compile
21 | ```
22 |
23 | You may have a different location for `ivy` therefore the location of the `ivy.jar` is configurable via the `build.properties` file. Use the example `build.properties_example` for setting it properly.
24 |
25 | Running the test cases:
26 | ```bash
27 | % ant test
28 | ```
29 |
30 | Cleaning up:
31 | ```bash
32 | % ant clean
33 | ```
--------------------------------------------------------------------------------
/build.properties_sample:
--------------------------------------------------------------------------------
1 | ivy.jar = /home/user/downloads/apache-ivy-2.3.0-rc1/ivy-2.3.0-rc1.jar
2 |
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/ivy.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/main/java/com/zsoltfabok/blog/Munger.java:
--------------------------------------------------------------------------------
1 | package com.zsoltfabok.blog;
2 |
3 | import org.springframework.stereotype.Component;
4 |
5 | @Component
6 | public class Munger {
7 |
8 | public String munge(String word) {
9 | if (word.length() < 3) {
10 | return word;
11 | } else {
12 | StringBuilder temp = new StringBuilder(word);
13 | temp = temp.reverse();
14 | return switchFirstAndLastCharacters(temp).toString();
15 | }
16 | }
17 |
18 | private StringBuilder switchFirstAndLastCharacters(StringBuilder word) {
19 | char lastCharacter = word.charAt(word.length() - 1);
20 | word.setCharAt(word.length() - 1, word.charAt(0));
21 | word.setCharAt(0, lastCharacter);
22 | return word;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/zsoltfabok/blog/SentenceHelper.java:
--------------------------------------------------------------------------------
1 | package com.zsoltfabok.blog;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import org.springframework.stereotype.Component;
7 |
8 | @Component
9 | public class SentenceHelper {
10 |
11 | private static final String SEPARATOR = " ";
12 |
13 | public List split(String sentence) {
14 | List words = new ArrayList();
15 | for (String word : sentence.split(SEPARATOR)) {
16 | words.add(word);
17 | }
18 | return words;
19 | }
20 |
21 | public String join(List words) {
22 | StringBuilder sentence = new StringBuilder();
23 | for (String word : words) {
24 | sentence.append(word).append(SEPARATOR);
25 | }
26 | return sentence.toString().trim();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/zsoltfabok/blog/SimpleTextMunger.java:
--------------------------------------------------------------------------------
1 | package com.zsoltfabok.blog;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.stereotype.Component;
7 |
8 | @Component
9 | public class SimpleTextMunger {
10 |
11 | private final SentenceHelper sentenceHelper;
12 | private final Munger munger;
13 |
14 | @Autowired
15 | public SimpleTextMunger(SentenceHelper sentenceHelper, Munger munger) {
16 | this.sentenceHelper = sentenceHelper;
17 | this.munger = munger;
18 | }
19 |
20 | public String execute(String sentence) {
21 | List words = sentenceHelper.split(sentence);
22 | for (int i = 0; i < words.size(); i++) {
23 | words.set(i, munger.munge(words.get(i)));
24 | }
25 | return sentenceHelper.join(words);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/zsoltfabok/blog/web/controller/MungerController.java:
--------------------------------------------------------------------------------
1 | package com.zsoltfabok.blog.web.controller;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.ui.Model;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RequestMethod;
8 | import org.springframework.web.bind.annotation.RequestParam;
9 |
10 | import com.zsoltfabok.blog.SimpleTextMunger;
11 |
12 | @Controller
13 | public class MungerController {
14 |
15 | @Autowired
16 | private SimpleTextMunger munger;
17 |
18 | @RequestMapping("/")
19 | public String show() {
20 | return "index";
21 | }
22 |
23 | @RequestMapping(value = "/munge", method=RequestMethod.POST)
24 | public String munge(@RequestParam("text") String text, Model model) {
25 | model.addAttribute("munged", munger.execute(text));
26 | model.addAttribute("original", text);
27 | return "index";
28 | }
29 | }
--------------------------------------------------------------------------------
/src/main/resources/applicationContext.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/munger-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | /WEB-INF/views/
21 |
22 |
23 | .jsp
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/views/index.jsp:
--------------------------------------------------------------------------------
1 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
2 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
3 | <%@ page isELIgnored="false" %>
4 |
5 |
6 | App
7 |
8 |
9 |
14 |
15 | munged: ${munged} (${original})
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | munger
8 | org.springframework.web.servlet.DispatcherServlet
9 | 1
10 |
11 |
12 |
13 | munger
14 | /
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/test/java/com/zsoltfabok/blog/EmbeddedTomcat.java:
--------------------------------------------------------------------------------
1 | package com.zsoltfabok.blog;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 |
6 | import org.apache.catalina.LifecycleException;
7 | import org.apache.catalina.startup.Tomcat;
8 | import org.apache.commons.io.FileUtils;
9 |
10 | public class EmbeddedTomcat {
11 | private Tomcat tomcat;
12 |
13 | public void start() {
14 | try {
15 | tomcat = new Tomcat();
16 | // If I don't want to copy files around then the base directory must be '.'
17 | String baseDir = ".";
18 | tomcat.setPort(8090);
19 | tomcat.setBaseDir(baseDir);
20 | tomcat.getHost().setAppBase(baseDir);
21 | tomcat.getHost().setDeployOnStartup(true);
22 | tomcat.getHost().setAutoDeploy(true);
23 | tomcat.start();
24 | } catch (LifecycleException e) {
25 | throw new RuntimeException(e);
26 | }
27 | }
28 |
29 | public void stop() {
30 | try {
31 | tomcat.stop();
32 | tomcat.destroy();
33 | // Tomcat creates a work folder where the temporary files are stored
34 | FileUtils.deleteDirectory(new File("work"));
35 | FileUtils.deleteDirectory(new File("tomcat.8080"));
36 | } catch (LifecycleException e) {
37 | throw new RuntimeException(e);
38 | } catch (IOException e) {
39 | throw new RuntimeException(e);
40 | }
41 | }
42 |
43 | public void deploy(String appName) {
44 | tomcat.addWebapp(tomcat.getHost(), "/" + appName, "src/main/webapp");
45 | }
46 |
47 | public String getApplicationUrl(String appName) {
48 | return String.format("http://%s:%d/%s", tomcat.getHost().getName(),
49 | tomcat.getConnector().getLocalPort(), appName);
50 | }
51 |
52 | public boolean isRunning() {
53 | return tomcat != null;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/test/java/com/zsoltfabok/blog/SimpleTextMungerStepsdef.java:
--------------------------------------------------------------------------------
1 | package com.zsoltfabok.blog;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.mockito.Mockito.mock;
5 | import static org.mockito.Mockito.when;
6 | import cucumber.annotation.en.Given;
7 | import cucumber.annotation.en.Then;
8 | import cucumber.annotation.en.When;
9 |
10 | public class SimpleTextMungerStepsdef {
11 |
12 | private SimpleTextMunger simpleTextMunger;
13 | private Munger munger;
14 | private SentenceHelper sentenceHelper;
15 | private String result;
16 | private String inputWord;
17 | private String mungedWord;
18 |
19 | @Given("^I have a mocked munger which always returns \"([^\"]*)\" for \"([^\"]*)\"$")
20 | public void I_have_a_mocked_munger_which_always_returns_(String munged, String word) {
21 | munger = mock(Munger.class);
22 | inputWord = word;
23 | mungedWord = munged;
24 | }
25 |
26 | @Given("^I have an instance of my class$")
27 | public void I_have_an_instance_of_my_class() {
28 | sentenceHelper = new SentenceHelper();
29 | simpleTextMunger = new SimpleTextMunger(sentenceHelper, munger);
30 | }
31 |
32 |
33 | @When("^I call my method with \"([^\"]*)\"$")
34 | public void I_call_my_method_with_(String word) {
35 | when(munger.munge(inputWord)).thenReturn(mungedWord);
36 | result = simpleTextMunger.execute(word);
37 | }
38 |
39 | @Then("^I receive \"([^\"]*)\"$")
40 | public void I_receive_(String expectation) {
41 | assertEquals(expectation, result);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/test/java/com/zsoltfabok/blog/SimpleTextMunger_Test.java:
--------------------------------------------------------------------------------
1 | package com.zsoltfabok.blog;
2 |
3 | import org.junit.runner.RunWith;
4 | import cucumber.junit.Cucumber;
5 |
6 | @RunWith(Cucumber.class)
7 | @Cucumber.Options(features="classpath:simple_text_munger.feature")
8 | public class SimpleTextMunger_Test {
9 | }
10 |
--------------------------------------------------------------------------------
/src/test/java/com/zsoltfabok/blog/WebTextMungerStepsdef.java:
--------------------------------------------------------------------------------
1 | package com.zsoltfabok.blog;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.openqa.selenium.By;
6 | import org.openqa.selenium.WebDriver;
7 | import org.openqa.selenium.firefox.FirefoxDriver;
8 |
9 | import cucumber.annotation.Before;
10 | import cucumber.annotation.en.Given;
11 | import cucumber.annotation.en.Then;
12 | import cucumber.annotation.en.When;
13 |
14 | public class WebTextMungerStepsdef {
15 |
16 | private static EmbeddedTomcat tomcat = new EmbeddedTomcat();
17 | private static WebDriver browser;
18 |
19 | @Before("@web")
20 | public void beforeScenario() {
21 | if (!tomcat.isRunning()) {
22 | tomcat.start();
23 | tomcat.deploy("munger");
24 | browser = new FirefoxDriver();
25 |
26 | Runtime.getRuntime().addShutdownHook(new Thread() {
27 | public void run() {
28 | browser.close();
29 | tomcat.stop();
30 | }
31 | });
32 | }
33 | }
34 |
35 | @Given("^I am on the home page")
36 | public void I_am_on_the_home_page() {
37 | browser.get(tomcat.getApplicationUrl("munger"));
38 | }
39 |
40 | @When("^I enter \"([^\"]*)\"$")
41 | public void I_enter_(String text) {
42 | browser.findElement(By.id("text")).sendKeys(text);
43 | }
44 |
45 | @When("^I press \"([^\"]*)\"$")
46 | public void I_press_(String buttonId) {
47 | browser.findElement(By.id(buttonId)).click();
48 | }
49 |
50 | @Then("^I see \"([^\"]*)\" as the munged text$")
51 | public void I_see_as_the_munged_text(String text) {
52 | assertEquals(text, browser.findElement(By.id("munged")).getText());
53 | }
54 |
55 | @Then("^I see \"([^\"]*)\" as the original$")
56 | public void I_see_as_the_original(String text) {
57 | assertEquals("(" + text + ")", browser.findElement(By.id("original")).getText());
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/test/java/com/zsoltfabok/blog/WebTextMunger_Test.java:
--------------------------------------------------------------------------------
1 | package com.zsoltfabok.blog;
2 |
3 | import org.junit.runner.RunWith;
4 |
5 | import cucumber.junit.Cucumber;
6 |
7 | @RunWith(Cucumber.class)
8 | @Cucumber.Options(features="classpath:web_text_munger.feature")
9 | public class WebTextMunger_Test {
10 | }
11 |
--------------------------------------------------------------------------------
/src/test/java/com/zsoltfabok/blog/spring/SimpleTextMungerTest.java:
--------------------------------------------------------------------------------
1 | package com.zsoltfabok.blog.spring;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Test;
6 | import org.junit.runner.RunWith;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.test.context.ContextConfiguration;
9 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
10 |
11 | import com.zsoltfabok.blog.SimpleTextMunger;
12 |
13 | @RunWith(SpringJUnit4ClassRunner.class)
14 | @ContextConfiguration(locations = { "/applicationContext.xml" })
15 | public class SimpleTextMungerTest {
16 | @Autowired
17 | private SimpleTextMunger simpleTextMunger;
18 |
19 | @Test
20 | public void shouldMungeASimpleWord() {
21 | assertEquals("wrod", simpleTextMunger.execute("word"));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/resources/cucumber.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/test/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=WARN, stdout
3 |
4 | # Direct log messages to stdout
5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6 | log4j.appender.stdout.Target=System.out
7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/src/test/resources/simple_text_munger.feature:
--------------------------------------------------------------------------------
1 | Feature: simple text munger kata
2 |
3 | Scenario: It should process a sentence
4 | Given I have a mocked munger which always returns "folw" for "flow"
5 | And I have an instance of my class
6 | When I call my method with "flow flow"
7 | Then I receive "folw folw"
--------------------------------------------------------------------------------
/src/test/resources/web_text_munger.feature:
--------------------------------------------------------------------------------
1 | Feature: web text munger kata
2 |
3 | @web
4 | Scenario: It should process a sentence
5 | Given I am on the home page
6 | When I enter "flow flow"
7 | And I press "submit"
8 | Then I see "folw folw" as the munged text
9 | And I see "flow flow" as the original
10 |
--------------------------------------------------------------------------------