-
Notifications
You must be signed in to change notification settings - Fork 23
Make randomOrder configuration, allowing tests to be run in any order… #128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ashleyfrieze
wants to merge
1
commit into
greghaskins:master
Choose a base branch
from
ashleyfrieze:RandomOrder
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
12 changes: 12 additions & 0 deletions
12
src/main/java/com/greghaskins/spectrum/internal/ExecutionSequenceApplier.java
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.greghaskins.spectrum.internal; | ||
|
||
/** | ||
* Tagging interface for a {@link Parent} that sequences its children. | ||
*/ | ||
public interface ExecutionSequenceApplier { | ||
/** | ||
* Attache the sequencing strategy. | ||
* @param sequencer execution sequencer that orders the children. | ||
*/ | ||
void setSequencer(ExecutionSequencer sequencer); | ||
} |
18 changes: 18 additions & 0 deletions
18
src/main/java/com/greghaskins/spectrum/internal/ExecutionSequencer.java
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.greghaskins.spectrum.internal; | ||
|
||
import java.util.List; | ||
|
||
/** | ||
* Put the children into an execution order. | ||
*/ | ||
@FunctionalInterface | ||
public interface ExecutionSequencer { | ||
ExecutionSequencer DEFAULT = list -> list; | ||
|
||
/** | ||
* Apply the ordering to the list of children. | ||
* @param originalOrder order they are stored | ||
* @return re-ordered | ||
*/ | ||
List<Child> sequence(List<Child> originalOrder); | ||
} |
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
53 changes: 53 additions & 0 deletions
53
src/main/java/com/greghaskins/spectrum/internal/configuration/BlockRandomOrder.java
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.greghaskins.spectrum.internal.configuration; | ||
|
||
import com.greghaskins.spectrum.internal.Child; | ||
import com.greghaskins.spectrum.internal.ExecutionSequenceApplier; | ||
import com.greghaskins.spectrum.internal.ExecutionSequencer; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Random; | ||
|
||
/** | ||
* Configuration block that randomises the order of tests in their parent. | ||
*/ | ||
public class BlockRandomOrder implements BlockConfigurable<BlockTimeout>, ExecutionSequencer { | ||
private Random random; | ||
|
||
public BlockRandomOrder() { | ||
this(System.currentTimeMillis()); | ||
} | ||
|
||
public BlockRandomOrder(long seed) { | ||
random = new Random(seed); | ||
System.out.println("Random execution order set using seed: " + seed); | ||
} | ||
|
||
@Override | ||
public boolean inheritedByChild() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public void applyTo(Child child, TaggingFilterCriteria state) { | ||
if (child instanceof ExecutionSequenceApplier) { | ||
((ExecutionSequenceApplier) child).setSequencer(this); | ||
} | ||
} | ||
|
||
@Override | ||
public BlockConfigurable<BlockTimeout> merge(BlockConfigurable<?> other) { | ||
// my value supersedes any inherited value | ||
|
||
return this; | ||
} | ||
|
||
@Override | ||
public List<Child> sequence(List<Child> originalOrder) { | ||
List<Child> result = new ArrayList<>(originalOrder); | ||
Collections.shuffle(result, random); | ||
|
||
return result; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package specs; | ||
|
||
import static com.greghaskins.spectrum.Configure.randomOrder; | ||
import static com.greghaskins.spectrum.Configure.with; | ||
import static com.greghaskins.spectrum.Spectrum.describe; | ||
import static com.greghaskins.spectrum.Spectrum.it; | ||
import static com.greghaskins.spectrum.dsl.gherkin.Gherkin.*; | ||
import static java.util.stream.Collectors.toList; | ||
import static junit.framework.TestCase.fail; | ||
import static org.hamcrest.CoreMatchers.not; | ||
import static org.hamcrest.Matchers.contains; | ||
import static org.hamcrest.core.Is.is; | ||
import static org.junit.Assert.assertThat; | ||
|
||
import com.greghaskins.spectrum.BlockConfigurationChain; | ||
import com.greghaskins.spectrum.Spectrum; | ||
import com.greghaskins.spectrum.SpectrumHelper; | ||
|
||
import org.junit.runner.Result; | ||
import org.junit.runner.RunWith; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
@RunWith(Spectrum.class) | ||
public class RandomOrderSpecs { | ||
{ | ||
describe("Random order specs", () -> { | ||
it("can execute at all", () -> { | ||
Result result = SpectrumHelper.run(() -> { | ||
buildSuite(randomOrder()); | ||
}); | ||
assertThat(result.getRunCount(), is(6)); | ||
}); | ||
|
||
it("will have different execution order each time", () -> { | ||
List<String> originalFailures = failureList(SpectrumHelper.run(() -> { | ||
buildSuite(randomOrder()); | ||
})); | ||
|
||
// as we are dealing with random numbers, it may take a few goes before a new | ||
// permutation comes up | ||
int iteration = 0; | ||
Result nextResult; | ||
do { | ||
nextResult = SpectrumHelper.run(() -> { | ||
buildSuite(randomOrder()); | ||
}); | ||
iteration++; | ||
} while (iteration < 100 && failureList(nextResult).equals(originalFailures)); | ||
|
||
// should not have reached the limit where we gave up finding a new one | ||
assertThat(iteration, not(is(100))); | ||
}); | ||
|
||
it("can have the same execution order each time with a seed", () -> { | ||
Result result1 = SpectrumHelper.run(() -> { | ||
buildSuite(randomOrder(12345)); | ||
}); | ||
Result result2 = SpectrumHelper.run(() -> { | ||
buildSuite(randomOrder(12345)); | ||
}); | ||
|
||
assertThat(failureList(result1), is(failureList(result2))); | ||
}); | ||
|
||
describe("composite tests", with(randomOrder(), () -> { | ||
scenario("a test that relies on order in a random order tree", () -> { | ||
final List<String> strings = new ArrayList<>(); | ||
given("first step adds first", () -> { | ||
strings.add("first"); | ||
}); | ||
when("second step adds second", () -> { | ||
strings.add("second"); | ||
}); | ||
and("third step adds third", () -> { | ||
strings.add("third"); | ||
}); | ||
then("the order is correct", () -> { | ||
assertThat(strings, contains("first", "second", "third")); | ||
}); | ||
}); | ||
})); | ||
}); | ||
} | ||
|
||
private List<String> failureList(Result result) { | ||
return result.getFailures().stream() | ||
.map(failure -> failure.getDescription().getMethodName()) | ||
.collect(toList()); | ||
} | ||
|
||
private static void buildSuite(BlockConfigurationChain order) { | ||
// each test fails so we can use the failures to determine if they were random | ||
describe("Tests in random order", with(order, () -> { | ||
describe("scramble each level of the hierarchy", () -> { | ||
it("happens whenever", () -> { | ||
fail(); | ||
}); | ||
it("happens after or before", () -> { | ||
fail(); | ||
}); | ||
it("can happen when it likes", () -> { | ||
fail(); | ||
}); | ||
}); | ||
describe("make each level of the hierarchy different", () -> { | ||
it("then happens whenever", () -> { | ||
fail(); | ||
}); | ||
it("then happens after or before", () -> { | ||
fail(); | ||
}); | ||
it("then can happen when it likes", () -> { | ||
fail(); | ||
}); | ||
}); | ||
})); | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ashleyfrieze Do you imagine needing more than these specs here ☝️ to sufficiently test the Gherkin-style DSL? This scenario seems pretty straightforward to me. I guess you might have a mixed
describe
where some pieces run in random order, but the right things (given/when/then) stay in the right order.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These do look like they cover the scenario. I've a funny feeling there was something else worrying me about the feature, perhaps relating back to the bug I found in the gherkin tests. If you're going to merge PR #127, why don't we review this again after rebasing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. We'll look at it again after #127