From d2e58a4f1d1fdfeadc1b281ddeda3d3a947efd52 Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Fri, 19 Feb 2016 16:53:10 -0800 Subject: [PATCH 1/2] Make sure afterEach still runs when a test fails --- .../java/com/greghaskins/spectrum/Suite.java | 4 +- .../greghaskins/spectrum/TryFinallyBlock.java | 25 +++++++++ src/test/java/specs/FixturesSpec.java | 51 +++++++++++++++++-- 3 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/greghaskins/spectrum/TryFinallyBlock.java diff --git a/src/main/java/com/greghaskins/spectrum/Suite.java b/src/main/java/com/greghaskins/spectrum/Suite.java index 733c161..0d4c347 100644 --- a/src/main/java/com/greghaskins/spectrum/Suite.java +++ b/src/main/java/com/greghaskins/spectrum/Suite.java @@ -47,8 +47,8 @@ public Suite addSuite(final String name) { public Spec addSpec(final String name, final Block block) { final Description specDescription = Description.createTestDescription(this.description.getClassName(), name); - final CompositeBlock specBlockInContext = new CompositeBlock( - Arrays.asList(this.beforeAll, this.beforeEach, block, this.afterEach)); + final Block specBlockInContext = new TryFinallyBlock(new CompositeBlock( + Arrays.asList(this.beforeAll, this.beforeEach, block)), this.afterEach); final Spec spec = new Spec(specDescription, specBlockInContext, this); addChild(spec); diff --git a/src/main/java/com/greghaskins/spectrum/TryFinallyBlock.java b/src/main/java/com/greghaskins/spectrum/TryFinallyBlock.java new file mode 100644 index 0000000..c670cec --- /dev/null +++ b/src/main/java/com/greghaskins/spectrum/TryFinallyBlock.java @@ -0,0 +1,25 @@ +package com.greghaskins.spectrum; + +import com.greghaskins.spectrum.Spectrum.Block; + +class TryFinallyBlock implements Block { + + private final Block tryBlock; + private final Block finallyBlock; + + public TryFinallyBlock(final Block tryBlock, final Block finallyBlock) { + this.tryBlock = tryBlock; + this.finallyBlock = finallyBlock; + } + + @Override + public void run() throws Throwable { + try { + tryBlock.run(); + } finally { + finallyBlock.run(); + } + + } + +} diff --git a/src/test/java/specs/FixturesSpec.java b/src/test/java/specs/FixturesSpec.java index d2412ec..97cf4f3 100644 --- a/src/test/java/specs/FixturesSpec.java +++ b/src/test/java/specs/FixturesSpec.java @@ -10,6 +10,7 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; @@ -274,6 +275,20 @@ public class FixturesSpec {{ }); + describe("afterEach blocks", () -> { + + describe("when a spec explodes", () -> { + + it("still run", () -> { + final Result result = SpectrumRunner.run(getSuiteWithExplodingSpec()); + assertThat(result.getFailureCount(), is(1)); + assertThat(result.getFailures().get(0).getMessage(), containsString("boom")); + }); + + }); + + }); + } private static Class getSpecWithExplodingBeforeEach(){ @@ -375,11 +390,39 @@ class Spec {{ }); - }); - }); + }); + }); - }} - return Spec.class; + }} + return Spec.class; +} + +private static Class getSuiteWithExplodingSpec(){ + + class Suite {{ + describe("suite with exploding spec", () -> { + + final ArrayList items = new ArrayList<>(); + + describe("boom", () -> { + it("explodes", () -> { + items.add("foo"); + throw new Exception("boom"); + }); + + afterEach(()->{ + items.clear(); + }); + }); + + it("should still run afterEach blocks", () -> { + assertThat(items, hasSize(0)); + }); + + + }); + }} + return Suite.class; } } From 7d14b66f1be4bf2a77056d75b7d3606adfc85722 Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Fri, 19 Feb 2016 17:18:28 -0800 Subject: [PATCH 2/2] Run all afterEach even if one fails --- .../greghaskins/spectrum/AfterEachBlock.java | 36 ++++++++++ .../java/com/greghaskins/spectrum/Suite.java | 2 +- src/test/java/specs/FixturesSpec.java | 65 +++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/greghaskins/spectrum/AfterEachBlock.java diff --git a/src/main/java/com/greghaskins/spectrum/AfterEachBlock.java b/src/main/java/com/greghaskins/spectrum/AfterEachBlock.java new file mode 100644 index 0000000..61c998e --- /dev/null +++ b/src/main/java/com/greghaskins/spectrum/AfterEachBlock.java @@ -0,0 +1,36 @@ +package com.greghaskins.spectrum; + +import java.util.ArrayList; +import java.util.List; + +import com.greghaskins.spectrum.Spectrum.Block; + +class AfterEachBlock implements Block { + + private final List blocks; + + public AfterEachBlock() { + this.blocks = new ArrayList(); + } + + @Override + public void run() throws Throwable { + runAllBlocksInReverseOrder(this.blocks.size() - 1); + } + + private void runAllBlocksInReverseOrder(final int index) throws Throwable { + if (index < 0) { + return; + } + try { + this.blocks.get(index).run(); + } finally { + runAllBlocksInReverseOrder(index - 1); + } + } + + public void addBlock(final Block block) { + this.blocks.add(block); + } + +} diff --git a/src/main/java/com/greghaskins/spectrum/Suite.java b/src/main/java/com/greghaskins/spectrum/Suite.java index 0d4c347..56ca723 100644 --- a/src/main/java/com/greghaskins/spectrum/Suite.java +++ b/src/main/java/com/greghaskins/spectrum/Suite.java @@ -18,7 +18,7 @@ class Suite implements Parent, Child { private final CompositeBlock afterAll = new CompositeBlock(); private final CompositeBlock beforeEach = new CompositeBlock(); - private final CompositeBlock afterEach = new CompositeBlock(); + private final AfterEachBlock afterEach = new AfterEachBlock(); private final List children = new ArrayList(); private final Set focusedChildren = new HashSet(); diff --git a/src/test/java/specs/FixturesSpec.java b/src/test/java/specs/FixturesSpec.java index 97cf4f3..690bd3e 100644 --- a/src/test/java/specs/FixturesSpec.java +++ b/src/test/java/specs/FixturesSpec.java @@ -287,6 +287,40 @@ public class FixturesSpec {{ }); + describe("when another afterEach explodes", () -> { + + it("still run, too", () -> { + final Result result = SpectrumRunner.run(getSuiteWithExplodingAndNonExplodingAfterEach()); + assertThat(result.getFailureCount(), is(1)); + assertThat(result.getFailures().get(0).getMessage(), containsString("boom")); + }); + + }); + + final ArrayList items = new ArrayList<>(); + + describe("in multiples", () -> { + + it("run in reverse order", () -> { + assertThat(items, hasSize(0)); + }); + + afterEach(() -> { + items.add("after1"); + }); + afterEach(() -> { + items.add("after2"); + }); + afterEach(() -> { + items.add("after3"); + }); + + }); + + it("run in reverse declaration order", () -> { + assertThat(items, contains("after3", "after2", "after1")); + }); + }); } @@ -425,4 +459,35 @@ class Suite {{ return Suite.class; } +private static Class getSuiteWithExplodingAndNonExplodingAfterEach(){ + + class Suite {{ + describe("suite with exploding spec", () -> { + + final ArrayList items = new ArrayList<>(); + + describe("boom", () -> { + it("explodes", () -> { + items.add("foo"); + }); + + afterEach(() -> { + throw new Exception("boom"); + }); + + afterEach(()->{ + items.clear(); + }); + }); + + it("should still run afterEach blocks", () -> { + assertThat(items, hasSize(0)); + }); + + + }); + }} + return Suite.class; +} + }