Skip to content

Commit

Permalink
Merge pull request #3 from peterklijn/f-implementations
Browse files Browse the repository at this point in the history
F implementations
  • Loading branch information
peterklijn authored Mar 27, 2017
2 parents 03dcc44 + 97b16cf commit 25c802b
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,28 @@ public static void describe(String text, Invokable block) {
suiteBuilder.describe(text, block);
}

/**
* Creates a focussed test suite.
* <p>Test suites can contain:
* <ul>
* <li>specs (defined by using {@code it()}</li>
* <li>other suites (defined by nesting {@code describe()} calls)</li>
* <li>{@code beforeEach()} and {@code afterEach()} handlers.</li>
* </ul>
* <p>For example:
* <pre>{@code
* fdescribe("my test suite", () -> {
* ...
* });
* }</pre>
* @param text A description of the test suite
* @param block A code block that represents the test suite
*/
public static void fdescribe(String text, Invokable block) {
failIfNoSuiteBuilderAvailable("fdescribe");
suiteBuilder.fdescribe(text, block);
}

/**
* Creates a pending test suite.
* <p>Test suites can contain:
Expand Down Expand Up @@ -98,6 +120,23 @@ public static void it(String text, Invokable block) {
suiteBuilder.it(text, block);
}

/**
* Create a new focussed spec.
* <p>Focussed specs are used to temporarily only run these tests and disable the other specs.
* <p>For example:
* <pre>{@code
* fit("returns a list containing one item", () -> {
* assertEquals(1, getList().size());
* });
* }</pre>
* @param text A description of the expected behavior
* @param block A code block that implements the validation
*/
public static void fit(String text, Invokable block) {
failIfNoSuiteBuilderAvailable("fit");
suiteBuilder.fit(text, block);
}

/**
* Create a new pending spec.
* <p>Pending specs are used to temporarily disable specs.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
public class SuiteBuilder {

private Map<String, Invokable> suiteDefinitions;
private Map<String, Invokable> focusedSuiteDefinitions;
private Map<String, Optional<Invokable>> specDefinitions;
private Map<String, Optional<Invokable>> focusedSpecDefinitions;
private List<Invokable> beforeEachHandlers;
private List<Invokable> beforeHandlers;
private List<Invokable> afterEachHandlers;
Expand All @@ -40,7 +42,9 @@ public SuiteBuilder() {

private void prepare() {
this.suiteDefinitions = new LinkedHashMap<>();
this.focusedSuiteDefinitions = new LinkedHashMap<>();
this.specDefinitions = new LinkedHashMap<>();
this.focusedSpecDefinitions = new LinkedHashMap<>();
this.beforeHandlers = new ArrayList<>();
this.afterHandlers = new ArrayList<>();
this.beforeEachHandlers = new ArrayList<>();
Expand All @@ -60,13 +64,18 @@ public void describe(String description, Invokable definition) {
this.suiteDefinitions.put(description, definition);
}

public void fdescribe(String description, Invokable definition) {
throwExceptionWhenSuiteDescriptionExists(description);
this.focusedSuiteDefinitions.put(description, definition);
}

public void xdescribe(String description, PendingInvokable definition) {
throwExceptionWhenSuiteDescriptionExists(description);
this.suiteDefinitions.put(description, definition);
}

private void throwExceptionWhenSuiteDescriptionExists(final String description) {
if (this.suiteDefinitions.containsKey(description)) {
if (this.suiteDefinitions.containsKey(description) || this.focusedSuiteDefinitions.containsKey(description)) {
throw new IllegalArgumentException(String.format("Suite with description '%s' does already exist", description));
}
}
Expand All @@ -76,13 +85,18 @@ public void it(String description, Invokable definition) {
this.specDefinitions.put(description, Optional.of(definition));
}

public void fit(String description, Invokable definition) {
throwExceptionWhenSpecDescriptionExists(description);
this.focusedSpecDefinitions.put(description, Optional.of(definition));
}

public void xit(String description) {
throwExceptionWhenSpecDescriptionExists(description);
this.specDefinitions.put(description, Optional.empty());
}

private void throwExceptionWhenSpecDescriptionExists(final String description) {
if (this.specDefinitions.containsKey(description)) {
if (this.specDefinitions.containsKey(description) || this.focusedSpecDefinitions.containsKey(description)) {
throw new IllegalArgumentException(String.format("Spec with description '%s' does already exist", description));
}
}
Expand All @@ -107,10 +121,18 @@ public Map<String, Invokable> getSuiteDefinitions() {
return suiteDefinitions;
}

public Map<String, Invokable> getFocusedSuiteDefinitions() {
return focusedSuiteDefinitions;
}

public Map<String, Optional<Invokable>> getSpecDefinitions() {
return specDefinitions;
}

public Map<String, Optional<Invokable>> getFocusedSpecDefinitions() {
return focusedSpecDefinitions;
}

public List<Invokable> getBeforeEachHandlers() {
return beforeEachHandlers;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
*/
package com.mscharhag.oleaster.runner.suite;

import java.util.Map;
import java.util.Optional;

import com.mscharhag.oleaster.runner.Invokable;

public class SuiteDefinitionEvaluator {


Expand Down Expand Up @@ -47,13 +50,24 @@ private Suite createSuite(SuiteDefinition suiteDefinition, SuiteBuilder suiteBui
suite.addAfterEachHandlers(suiteBuilder.getAfterEachHandlers());
suite.addAfterHandlers(suiteBuilder.getAfterHandlers());

suiteBuilder.getSpecDefinitions().forEach((description, block) ->
Map<String, Optional<Invokable>> specDefinitions = suiteBuilder.getFocusedSpecDefinitions().size() > 0
? suiteBuilder.getFocusedSpecDefinitions()
: suiteBuilder.getSpecDefinitions();

specDefinitions.forEach((description, block) ->
suite.addSpec(new Spec(suite, description, suiteDefinition.isPending() ? Optional.empty() : block)));

suiteBuilder.getSuiteDefinitions().forEach((description, block) -> {
SuiteDefinition childSuiteDefinition = new SuiteDefinition(suite, description, block, suiteDefinition.isPending());
suite.addChildSuite(this.evaluate(childSuiteDefinition, suiteBuilder));
});
if (suiteBuilder.getFocusedSuiteDefinitions().size() > 0) {
suiteBuilder.getFocusedSuiteDefinitions().forEach((description, block) -> {
SuiteDefinition childSuiteDefinition = new SuiteDefinition(suite, description, block, suiteDefinition.isPending());
suite.addChildSuite(this.evaluate(childSuiteDefinition, suiteBuilder));
});
} else {
suiteBuilder.getSuiteDefinitions().forEach((description, block) -> {
SuiteDefinition childSuiteDefinition = new SuiteDefinition(suite, description, block, suiteDefinition.isPending());
suite.addChildSuite(this.evaluate(childSuiteDefinition, suiteBuilder));
});
}

return suite;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.mscharhag.oleaster.runner;

import org.junit.runner.RunWith;

import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*;
import static org.junit.Assert.*;

@RunWith(OleasterRunner.class)
public class FocusedSpecTest {{
describe("The focused spec", () -> {

fit("is focused and will run", () -> {
assertTrue(true);
});

it("is not focused and will not run" , () -> {
fail("fail");
});

fdescribe("focused describe", () -> {
it("will run", () -> {
assertTrue(true);
});
it("will also run", () -> {
assertTrue(true);
});
});

fdescribe("another focused describe", () -> {
fit("is focused and will run", () -> {
assertTrue(true);
});

it("is not focused and will not run", () -> {
fail("fail");
});
});
});
}}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class SuiteDefinitionEvaluatorTest {

beforeEach(() -> {
sb = new SuiteBuilder();
StaticRunnerSupport.setSuiteBuilder(sb);
sde = new SuiteDefinitionEvaluator();
});

Expand Down Expand Up @@ -119,15 +120,15 @@ public class SuiteDefinitionEvaluatorTest {
final String DESC_TWO_ONE = "two > one";
beforeEach(() -> {
suite = sde.evaluate(new SuiteDefinition(null, DESC_ROOT, () -> {
sb.xdescribe(DESC_ONE, () -> {
sb.it("hello", () -> {
xdescribe(DESC_ONE, () -> {
it("hello", () -> {
fail("I should be removed");
});
});

sb.xdescribe(DESC_TWO, () -> {
sb.describe(DESC_TWO_ONE, () -> {
sb.it("hello", () -> {
xdescribe(DESC_TWO, () -> {
describe(DESC_TWO_ONE, () -> {
it("hello", () -> {
fail("I should be removed");
});
});
Expand All @@ -152,5 +153,91 @@ public class SuiteDefinitionEvaluatorTest {
});
});

describe("when a suite is focused", () -> {
final String DESC_ONE = "desc-one";
final String DESC_TWO = "desc-two";
final String IT_ONE = "it-one";
final String IT_TWO = "it-two";

beforeEach(() -> {
suite = sde.evaluate(new SuiteDefinition(null, "root", () -> {
describe(DESC_ONE, () -> {
it(IT_ONE, () -> fail("should not be found."));
});

fdescribe(DESC_TWO, () -> {
it(IT_TWO, () -> assertTrue(true));
});
}), sb);
});

it("should not find DESC_ONE nor IT_ONE", () -> {
assertEquals(1, suite.getSuites().size());
assertFalse(DESC_ONE.equals(suite.getSuites().get(0).getDescription()));
});

it("should find only DESC_TWO",() -> {
assertTrue(DESC_TWO.equals(suite.getSuites().get(0).getDescription()));
});
});

describe("with a more complex focused and pending suite collection", () -> {
final String DESC_ONE = "d1";
final String IT_ONE = "d1-i1";
final String DESC_TWO = "d2";
final String IT_TWO = "d2-i1";
final String DESC_THREE = "d3";
final String IT_THREE = "d3-i1";
final String IT_FOUR = "d3-i2";
final String IT_FIVE = "d3-i3";
beforeEach(() -> {
suite = sde.evaluate(new SuiteDefinition(null, "ROOT", () -> {
fdescribe(DESC_ONE, () -> {
it(IT_ONE, () -> assertTrue(true));
});

describe(DESC_TWO, () -> {
it("does not run", () -> fail("does not run"));
fit(IT_TWO, () -> assertTrue(true));
});

fdescribe(DESC_THREE, () -> {
it(IT_THREE, () -> assertTrue(true));
xit(IT_FOUR, () -> fail("does not run"));
it(IT_FIVE);
});
}), sb);
});

it("should run it's in the first focused describe", () -> {
assertEquals(DESC_ONE, suite.getSuites().get(0).getDescription());
assertEquals(1, suite.getSuites().get(0).getSpecs().size());
assertEquals(IT_ONE, suite.getSuites().get(0).getSpecs().get(0).getDescription());
});

it("should not run DESC_TWO", () -> {
assertEquals(2, suite.getSuites().size());
suite.getSuites().forEach(s -> assertNotEquals(DESC_TWO, s.getDescription()));
});

it("should not run it xit's in DESC_THREE", () -> {
final Suite d3 = suite.getSuites().get(1);
assertEquals(DESC_THREE, d3.getDescription());
assertEquals(3, d3.getSpecs().size());

assertEquals(IT_THREE, d3.getSpecs().get(0).getDescription());
assertTrue(d3.getSpecs().get(0).getBlock().isPresent());

assertEquals(IT_FOUR, d3.getSpecs().get(1).getDescription());
assertFalse(d3.getSpecs().get(1).getBlock().isPresent());
});

it("should not run it's without bodies", () -> {
final Suite d3 = suite.getSuites().get(1);

assertEquals(IT_FIVE, d3.getSpecs().get(2).getDescription());
assertFalse(d3.getSpecs().get(2).getBlock().isPresent());
});
});
});
}}

0 comments on commit 25c802b

Please sign in to comment.