Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c1e69ed32 | ||
|
|
2e12fdbd34 | ||
|
|
95a29a14fe | ||
|
|
d69cf31964 | ||
|
|
79c2f159e1 | ||
|
|
b99f90132a | ||
|
|
3d6b7b4d58 |
@@ -0,0 +1,24 @@
|
|||||||
|
package space.kklochko.simple_jbdd;
|
||||||
|
|
||||||
|
import space.kklochko.simple_jbdd.tests.factories.AbstractTestRunnerFactory;
|
||||||
|
import space.kklochko.simple_jbdd.tests.factories.SimpleTestRunnerFactory;
|
||||||
|
import space.kklochko.simple_jbdd.tests.loaders.NameClassLoader;
|
||||||
|
import space.kklochko.simple_jbdd.tests.reports.AbstractReporter;
|
||||||
|
import space.kklochko.simple_jbdd.tests.reports.CLIReporter;
|
||||||
|
import space.kklochko.simple_jbdd.tests.reports.fmt.SimpleTestReportFormatter;
|
||||||
|
import space.kklochko.simple_jbdd.tests.runners.CLITestRunner;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
NameClassLoader loader = new NameClassLoader();
|
||||||
|
AbstractTestRunnerFactory testRunnerFactory = new SimpleTestRunnerFactory();
|
||||||
|
AbstractReporter reporter = new CLIReporter(new SimpleTestReportFormatter());
|
||||||
|
|
||||||
|
CLITestRunner runner = new CLITestRunner(loader, testRunnerFactory, reporter);
|
||||||
|
|
||||||
|
boolean status = runner.run();
|
||||||
|
|
||||||
|
System.exit(status ? 0 : 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+1
-1
@@ -5,7 +5,7 @@ import space.kklochko.simple_jbdd.annotations.Title;
|
|||||||
import space.kklochko.simple_jbdd.tests.Test;
|
import space.kklochko.simple_jbdd.tests.Test;
|
||||||
|
|
||||||
|
|
||||||
@Title("A Simple Failed GivenWhenTest for Sum")
|
@Title("A Simple Failed Then Test for Sum")
|
||||||
public class SimpleFailedThenTest extends Test {
|
public class SimpleFailedThenTest extends Test {
|
||||||
@Then
|
@Then
|
||||||
public void check() {
|
public void check() {
|
||||||
|
|||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
package space.kklochko.simple_jbdd.test_examples.tests;
|
||||||
|
|
||||||
|
import space.kklochko.simple_jbdd.annotations.Given;
|
||||||
|
import space.kklochko.simple_jbdd.annotations.Then;
|
||||||
|
import space.kklochko.simple_jbdd.annotations.Title;
|
||||||
|
import space.kklochko.simple_jbdd.annotations.When;
|
||||||
|
import space.kklochko.simple_jbdd.test_examples.samples.Sum;
|
||||||
|
import space.kklochko.simple_jbdd.tests.Test;
|
||||||
|
|
||||||
|
@Title("A Simple GivenGivenWhenWhenThenThen Test for Sum")
|
||||||
|
public class SimpleGivenGivenWhenWhenThenThenTest extends Test {
|
||||||
|
private Sum sum;
|
||||||
|
private int a;
|
||||||
|
private int b;
|
||||||
|
private int c;
|
||||||
|
private int resultAB;
|
||||||
|
private int resultCB;
|
||||||
|
|
||||||
|
@Given("Create the Sum object")
|
||||||
|
void setup() {
|
||||||
|
sum = new Sum();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Given("Setup the arguments")
|
||||||
|
void setupArgs() {
|
||||||
|
a = 10;
|
||||||
|
b = 20;
|
||||||
|
c = 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Call the .sum(10, 20)")
|
||||||
|
void triggerAB() {
|
||||||
|
resultAB = sum.sum(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Call the .sum(30, 20)")
|
||||||
|
void triggerCB() {
|
||||||
|
resultCB = sum.sum(c, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("10 + 20 is 30")
|
||||||
|
void checkAB() {
|
||||||
|
assert 30 == resultAB;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("30 + 20 is 50")
|
||||||
|
void checkCB() {
|
||||||
|
assert 50 == resultCB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+1
-1
@@ -7,7 +7,7 @@ import space.kklochko.simple_jbdd.annotations.When;
|
|||||||
import space.kklochko.simple_jbdd.test_examples.samples.Sum;
|
import space.kklochko.simple_jbdd.test_examples.samples.Sum;
|
||||||
import space.kklochko.simple_jbdd.tests.Test;
|
import space.kklochko.simple_jbdd.tests.Test;
|
||||||
|
|
||||||
@Title("A Simple GivenWhenTest for Sum")
|
@Title("A Simple GivenWhenThen Test for Sum")
|
||||||
public class SimpleGivenWhenThenTest extends Test {
|
public class SimpleGivenWhenThenTest extends Test {
|
||||||
private Sum sum;
|
private Sum sum;
|
||||||
private int a;
|
private int a;
|
||||||
|
|||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package space.kklochko.simple_jbdd.tests.commands.decorators;
|
||||||
|
|
||||||
|
import space.kklochko.simple_jbdd.tests.Test;
|
||||||
|
import space.kklochko.simple_jbdd.tests.commands.AbstractTestCommand;
|
||||||
|
|
||||||
|
public class ErrorDecorator<T extends Test> extends AbstractDecorator<T> {
|
||||||
|
public ErrorDecorator(String error_label, AbstractTestCommand<T> command, String type) {
|
||||||
|
super(error_label, command);
|
||||||
|
setType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean test() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean runMethod() {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@@ -8,40 +8,55 @@ import space.kklochko.simple_jbdd.tests.Test;
|
|||||||
import space.kklochko.simple_jbdd.tests.commands.AbstractTestCommand;
|
import space.kklochko.simple_jbdd.tests.commands.AbstractTestCommand;
|
||||||
import space.kklochko.simple_jbdd.tests.commands.SimpleTestCommand;
|
import space.kklochko.simple_jbdd.tests.commands.SimpleTestCommand;
|
||||||
import space.kklochko.simple_jbdd.tests.commands.decorators.BlockDecorator;
|
import space.kklochko.simple_jbdd.tests.commands.decorators.BlockDecorator;
|
||||||
|
import space.kklochko.simple_jbdd.tests.commands.decorators.ErrorDecorator;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
public class TestCommandFactory {
|
public class TestCommandFactory {
|
||||||
public AbstractTestCommand create(Test input) {
|
public AbstractTestCommand create(Test input) {
|
||||||
Class<?> aClass = input.getClass();
|
Class<?> aClass = input.getClass();
|
||||||
Map<String, Method> test_methods = this.getTestMethods(aClass);
|
Map<String, ArrayList<Method>> test_methods = this.getTestMethods(aClass);
|
||||||
|
|
||||||
AbstractTestCommand<Test> aTestCommand = createTest(aClass, input);
|
AbstractTestCommand<Test> aTestCommand = createTest(aClass, input);
|
||||||
|
|
||||||
|
if(test_methods.size() == 0)
|
||||||
|
return new ErrorDecorator("ERROR!!! No blocks!!!", aTestCommand, "Error");
|
||||||
|
|
||||||
if(test_methods.containsKey("Then")) {
|
if(test_methods.containsKey("Then")) {
|
||||||
Method then = test_methods.get("Then");
|
ArrayList<Method> thens = getMethodsInReverseOrder(test_methods, "Then");
|
||||||
String label = then.getAnnotation(Then.class).value();
|
for(Method then : thens) {
|
||||||
aTestCommand = new BlockDecorator<Test>(label, aTestCommand, then, "Then");
|
String label = then.getAnnotation(Then.class).value();
|
||||||
|
aTestCommand = new BlockDecorator<Test>(label, aTestCommand, then, "Then");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(test_methods.containsKey("When")) {
|
if(test_methods.containsKey("When")) {
|
||||||
Method when = test_methods.get("When");
|
ArrayList<Method> whens = getMethodsInReverseOrder(test_methods, "When");
|
||||||
String label = when.getAnnotation(When.class).value();
|
for(Method when : whens) {
|
||||||
aTestCommand = new BlockDecorator<Test>(label, aTestCommand, when, "When");
|
String label = when.getAnnotation(When.class).value();
|
||||||
|
aTestCommand = new BlockDecorator<Test>(label, aTestCommand, when, "When");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(test_methods.containsKey("Given")) {
|
if(test_methods.containsKey("Given")) {
|
||||||
Method when = test_methods.get("Given");
|
ArrayList<Method> givens = getMethodsInReverseOrder(test_methods, "Given");
|
||||||
String label = when.getAnnotation(Given.class).value();
|
for(Method given : givens) {
|
||||||
aTestCommand = new BlockDecorator<Test>(label, aTestCommand, when, "Given");
|
String label = given.getAnnotation(Given.class).value();
|
||||||
|
aTestCommand = new BlockDecorator<Test>(label, aTestCommand, given, "Given");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return aTestCommand;
|
return aTestCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ArrayList<Method> getMethodsInReverseOrder(Map<String, ArrayList<Method>> test_methods, String key) {
|
||||||
|
ArrayList<Method> methods = test_methods.get(key);
|
||||||
|
Collections.reverse(methods);
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
protected AbstractTestCommand<Test> createTest(Class<?> aClass, Test input) {
|
protected AbstractTestCommand<Test> createTest(Class<?> aClass, Test input) {
|
||||||
Title aTitle = aClass.getAnnotation(Title.class);
|
Title aTitle = aClass.getAnnotation(Title.class);
|
||||||
String title = aClass.getName();
|
String title = aClass.getName();
|
||||||
@@ -52,8 +67,8 @@ public class TestCommandFactory {
|
|||||||
return new SimpleTestCommand<Test>(title, input);
|
return new SimpleTestCommand<Test>(title, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T extends Test> Map<String, Method> getTestMethods(Class<?> aClass) {
|
protected <T extends Test> Map<String, ArrayList<Method>> getTestMethods(Class<?> aClass) {
|
||||||
Map<String, Method> test_methods = new TreeMap<String, Method>();
|
Map<String, ArrayList<Method>> test_methods = new TreeMap<>();
|
||||||
|
|
||||||
for(Method method : aClass.getDeclaredMethods()) {
|
for(Method method : aClass.getDeclaredMethods()) {
|
||||||
Annotation[] annotations = method.getAnnotations();
|
Annotation[] annotations = method.getAnnotations();
|
||||||
@@ -62,15 +77,21 @@ public class TestCommandFactory {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(method.isAnnotationPresent(Given.class))
|
if(method.isAnnotationPresent(Given.class))
|
||||||
test_methods.put("Given", method);
|
addMethodTo(test_methods, "Given", method);
|
||||||
|
|
||||||
if(method.isAnnotationPresent(When.class))
|
if(method.isAnnotationPresent(When.class))
|
||||||
test_methods.put("When", method);
|
addMethodTo(test_methods, "When", method);
|
||||||
|
|
||||||
if(method.isAnnotationPresent(Then.class))
|
if(method.isAnnotationPresent(Then.class))
|
||||||
test_methods.put("Then", method);
|
addMethodTo(test_methods, "Then", method);
|
||||||
}
|
}
|
||||||
|
|
||||||
return test_methods;
|
return test_methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addMethodTo(Map<String, ArrayList<Method>> test_methods, String key, Method method) {
|
||||||
|
ArrayList<Method> methods = test_methods.getOrDefault(key, new ArrayList<>());
|
||||||
|
methods.add(method);
|
||||||
|
test_methods.put(key, methods);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
public class CLIReporter extends AbstractReporter {
|
public class CLIReporter extends AbstractReporter {
|
||||||
final int terminalWidth = 80;
|
final int terminalWidth = 80;
|
||||||
|
|
||||||
|
public CLIReporter(AbstractTestReportFormatter formatter) {
|
||||||
|
super(null, formatter);
|
||||||
|
}
|
||||||
|
|
||||||
public CLIReporter(ArrayList<AbstractMap.SimpleEntry<AbstractTestCommandMetaDataFactory, Boolean>> metadata, AbstractTestReportFormatter formatter) {
|
public CLIReporter(ArrayList<AbstractMap.SimpleEntry<AbstractTestCommandMetaDataFactory, Boolean>> metadata, AbstractTestReportFormatter formatter) {
|
||||||
super(metadata, formatter);
|
super(metadata, formatter);
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-27
@@ -1,5 +1,6 @@
|
|||||||
package space.kklochko.simple_jbdd.tests.factories
|
package space.kklochko.simple_jbdd.tests.factories
|
||||||
|
|
||||||
|
import space.kklochko.simple_jbdd.test_examples.tests.SimpleGivenGivenWhenWhenThenThenTest
|
||||||
import space.kklochko.simple_jbdd.test_examples.tests.SimpleGivenWhenThenTest
|
import space.kklochko.simple_jbdd.test_examples.tests.SimpleGivenWhenThenTest
|
||||||
import space.kklochko.simple_jbdd.test_examples.tests.SimpleThenTest
|
import space.kklochko.simple_jbdd.test_examples.tests.SimpleThenTest
|
||||||
import space.kklochko.simple_jbdd.test_examples.tests.SimpleThenTestWithoutTitle
|
import space.kklochko.simple_jbdd.test_examples.tests.SimpleThenTestWithoutTitle
|
||||||
@@ -14,19 +15,27 @@ those tests check if factory generate them right.
|
|||||||
""")
|
""")
|
||||||
@Title("Unit tests for TestCommandFactory")
|
@Title("Unit tests for TestCommandFactory")
|
||||||
class TestCommandFactorySpec extends Specification {
|
class TestCommandFactorySpec extends Specification {
|
||||||
def "If the map of methods have one test block."() {
|
def "The command have the same block count."() {
|
||||||
given: "I have a TestCommandFactory object"
|
given: "I have a TestCommandFactory object"
|
||||||
@Subject
|
@Subject
|
||||||
def factory = new TestCommandFactory();
|
def factory = new TestCommandFactory();
|
||||||
|
|
||||||
and: "I also have a SimpleThenTest object"
|
when: "If a test command have blocks"
|
||||||
def simpleThenTest = new SimpleThenTest()
|
def map = factory.getTestMethods(testClass.getClass())
|
||||||
|
|
||||||
when: "If a test have only one block"
|
def count = map.values()
|
||||||
def map = factory.getTestMethods(simpleThenTest.getClass())
|
.stream()
|
||||||
|
.map {it.size()}
|
||||||
|
.reduce(0) { acc, num -> acc + num }
|
||||||
|
|
||||||
then: "the map size is 1 method"
|
then: "the command have the expected block count"
|
||||||
1 == map.size()
|
expectedBlockCount == count
|
||||||
|
|
||||||
|
where:
|
||||||
|
testClass || expectedBlockCount
|
||||||
|
new SimpleThenTest() || 1
|
||||||
|
new SimpleGivenWhenThenTest() || 3
|
||||||
|
new SimpleGivenGivenWhenWhenThenThenTest() || 6
|
||||||
}
|
}
|
||||||
|
|
||||||
def "createTest() sets the title to a class name if no Title annotation."() {
|
def "createTest() sets the title to a class name if no Title annotation."() {
|
||||||
@@ -63,34 +72,22 @@ class TestCommandFactorySpec extends Specification {
|
|||||||
title == test.getLabels()['Title']
|
title == test.getLabels()['Title']
|
||||||
}
|
}
|
||||||
|
|
||||||
def "createTest() build a Test with only Then."() {
|
def "createTest() build a TestCommand that contains the expected blocks."() {
|
||||||
given: "I have a test factory"
|
given: "I have a test factory"
|
||||||
@Subject
|
@Subject
|
||||||
def factory = new TestCommandFactory()
|
def factory = new TestCommandFactory()
|
||||||
|
|
||||||
and: "I have a test class with Title"
|
|
||||||
def testClass = new SimpleThenTest()
|
|
||||||
|
|
||||||
when: "I build a test"
|
when: "I build a test"
|
||||||
def test = factory.create(testClass)
|
def test = factory.create(testClass)
|
||||||
|
|
||||||
then: "The test have title and then method"
|
then: "The test have the expected blocks"
|
||||||
['Title', 'Then'].toSet() == test.getLabels().keySet()
|
expectedBlocks.toSet() == test.getLabels().keySet()
|
||||||
}
|
|
||||||
|
|
||||||
def "createTest() build a Test with Given-When-Then."() {
|
where:
|
||||||
given: "I have a test factory"
|
testClass || expectedBlocks
|
||||||
@Subject
|
new SimpleThenTest() || ['Title', 'Then']
|
||||||
def factory = new TestCommandFactory()
|
new SimpleGivenWhenThenTest() || ['Title', 'Given', 'When', 'Then']
|
||||||
|
new SimpleGivenGivenWhenWhenThenThenTest() || ['Title', 'Given', 'When', 'Then']
|
||||||
and: "I have a test class with Title and Given-When-Then"
|
|
||||||
def testClass = new SimpleGivenWhenThenTest()
|
|
||||||
|
|
||||||
when: "I build a test"
|
|
||||||
def test = factory.create(testClass)
|
|
||||||
|
|
||||||
then: "The test have title and then method"
|
|
||||||
['Title', 'Given', 'When', 'Then'].toSet() == test.getLabels().keySet()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ class IntegratedClassLoader extends Specification {
|
|||||||
def classes = loader.load()
|
def classes = loader.load()
|
||||||
|
|
||||||
then: "Checking that the test result is expected"
|
then: "Checking that the test result is expected"
|
||||||
3 == classes.size()
|
4 == classes.size()
|
||||||
}
|
}
|
||||||
|
|
||||||
def "The classes must be represent the Test interface."() {
|
def "The classes must be represent the Test interface."() {
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ class IntegratedNameClassLoader extends Specification {
|
|||||||
def classNames = loader.load()
|
def classNames = loader.load()
|
||||||
|
|
||||||
then: "Checking that the test result is expected"
|
then: "Checking that the test result is expected"
|
||||||
3 == classNames.size()
|
4 == classNames.size()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-5
@@ -1,6 +1,7 @@
|
|||||||
package space.kklochko.simple_jbdd.tests.runners
|
package space.kklochko.simple_jbdd.tests.runners
|
||||||
|
|
||||||
import space.kklochko.simple_jbdd.test_examples.tests.SimpleFailedThenTest
|
import space.kklochko.simple_jbdd.test_examples.tests.SimpleFailedThenTest
|
||||||
|
import space.kklochko.simple_jbdd.test_examples.tests.SimpleGivenGivenWhenWhenThenThenTest
|
||||||
import space.kklochko.simple_jbdd.test_examples.tests.SimpleGivenWhenThenTest
|
import space.kklochko.simple_jbdd.test_examples.tests.SimpleGivenWhenThenTest
|
||||||
import space.kklochko.simple_jbdd.test_examples.tests.SimpleThenTest
|
import space.kklochko.simple_jbdd.test_examples.tests.SimpleThenTest
|
||||||
import space.kklochko.simple_jbdd.test_examples.tests.SimpleThenTestWithoutTitle
|
import space.kklochko.simple_jbdd.test_examples.tests.SimpleThenTestWithoutTitle
|
||||||
@@ -33,10 +34,11 @@ class IntegratedSimpleTestRunnerSpec extends Specification {
|
|||||||
result == expectedResult
|
result == expectedResult
|
||||||
|
|
||||||
where: "Possible variants of tests"
|
where: "Possible variants of tests"
|
||||||
testObject || expectedResult
|
testObject || expectedResult
|
||||||
new SimpleThenTest() || true
|
new SimpleThenTest() || true
|
||||||
new SimpleGivenWhenThenTest() || true
|
new SimpleGivenWhenThenTest() || true
|
||||||
new SimpleThenTestWithoutTitle() || true
|
new SimpleThenTestWithoutTitle() || true
|
||||||
new SimpleFailedThenTest() || false
|
new SimpleFailedThenTest() || false
|
||||||
|
new SimpleGivenGivenWhenWhenThenThenTest() || true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user