├── src ├── main │ ├── specnaz │ │ ├── build.gradle │ │ ├── src │ │ │ └── main │ │ │ │ └── java │ │ │ │ └── org │ │ │ │ └── specnaz │ │ │ │ ├── impl │ │ │ │ ├── Executable.java │ │ │ │ ├── SpecsRegistryViolation.java │ │ │ │ ├── SinglePositiveTestCase.java │ │ │ │ ├── TestCaseType.java │ │ │ │ ├── SpecDescriptor.java │ │ │ │ ├── ExecutableTestCase.java │ │ │ │ ├── TreeNode.java │ │ │ │ ├── SingleExceptionTestCase.java │ │ │ │ ├── SingleTestCase.java │ │ │ │ ├── SpecParser.java │ │ │ │ └── SpecsRegistry.java │ │ │ │ ├── params │ │ │ │ ├── RunnableParams1.java │ │ │ │ ├── impl │ │ │ │ │ ├── ParametrizedSubgroupInstance.java │ │ │ │ │ ├── ParametrizedSubgroup1.java │ │ │ │ │ ├── ParametrizedSubgroup2.java │ │ │ │ │ ├── ParametrizedSubgroup3.java │ │ │ │ │ ├── ParametrizedSubgroup4.java │ │ │ │ │ ├── ParametrizedPositiveTest1.java │ │ │ │ │ ├── AbstractParametrizedPositiveTest.java │ │ │ │ │ ├── ParametrizedPositiveTest2.java │ │ │ │ │ ├── ParametrizedSubgroup5.java │ │ │ │ │ ├── ParametrizedPositiveTest3.java │ │ │ │ │ ├── ParametrizedPositiveTest4.java │ │ │ │ │ ├── ParametrizedSubgroup6.java │ │ │ │ │ ├── ParametrizedPositiveTest5.java │ │ │ │ │ ├── ParametrizedPositiveTest6.java │ │ │ │ │ ├── ParametrizedExceptionTest1.java │ │ │ │ │ ├── ParametrizedPositiveTest7.java │ │ │ │ │ ├── ParametrizedSubgroup7.java │ │ │ │ │ ├── ParametrizedExceptionTest2.java │ │ │ │ │ ├── ParametrizedPositiveTest8.java │ │ │ │ │ ├── ParametrizedExceptionTest3.java │ │ │ │ │ ├── ParametrizedPositiveTest9.java │ │ │ │ │ ├── ParametrizedExceptionTest4.java │ │ │ │ │ ├── ParametrizedSubgroup8.java │ │ │ │ │ ├── ParametrizedExceptionTest5.java │ │ │ │ │ ├── ParametrizedExceptionTest6.java │ │ │ │ │ ├── ParametrizedSubgroup9.java │ │ │ │ │ ├── AbstractParametrizedExceptionTest.java │ │ │ │ │ ├── ParametrizedExceptionTest7.java │ │ │ │ │ ├── ParametrizedExceptionTest8.java │ │ │ │ │ ├── ParametrizedExceptionTest9.java │ │ │ │ │ ├── AbstractParametrizedTest.java │ │ │ │ │ └── AbstractParametrizedSubgroup.java │ │ │ │ ├── RunnableParams2.java │ │ │ │ ├── RunnableParams3.java │ │ │ │ ├── RunnableParams4.java │ │ │ │ ├── TestClosureParams1.java │ │ │ │ ├── RunnableParams5.java │ │ │ │ ├── TestClosureParams2.java │ │ │ │ ├── Params2.java │ │ │ │ ├── RunnableParams6.java │ │ │ │ ├── TestClosureParams3.java │ │ │ │ ├── RunnableParams7.java │ │ │ │ ├── RunnableParams8.java │ │ │ │ ├── TestClosureParams4.java │ │ │ │ ├── Params3.java │ │ │ │ ├── TestClosureParams5.java │ │ │ │ ├── RunnableParams9.java │ │ │ │ ├── TestClosureParams6.java │ │ │ │ ├── Params4.java │ │ │ │ ├── TestClosureParams7.java │ │ │ │ ├── TestClosureParams8.java │ │ │ │ ├── Params5.java │ │ │ │ ├── TestClosureParams9.java │ │ │ │ ├── Params6.java │ │ │ │ ├── Params7.java │ │ │ │ ├── Params8.java │ │ │ │ ├── ParamsExpectedSubgroup1.java │ │ │ │ ├── ParamsExpectedSubgroup2.java │ │ │ │ ├── ParamsExpectedSubgroup3.java │ │ │ │ ├── ParamsExpectedSubgroup4.java │ │ │ │ ├── ParamsExpectedSubgroup5.java │ │ │ │ ├── ParamsExpectedSubgroup6.java │ │ │ │ ├── Params9.java │ │ │ │ ├── ParamsExpectedSubgroup7.java │ │ │ │ ├── ParamsExpectedSubgroup8.java │ │ │ │ ├── ParamsExpectedSubgroup9.java │ │ │ │ ├── ParamsExpected1.java │ │ │ │ ├── ParamsExpected2.java │ │ │ │ ├── ParamsExpected3.java │ │ │ │ ├── ParamsExpected4.java │ │ │ │ ├── ParamsExpected5.java │ │ │ │ ├── ParamsExpected6.java │ │ │ │ ├── ParamsExpected7.java │ │ │ │ ├── ParamsExpectedException1.java │ │ │ │ ├── ParamsExpected8.java │ │ │ │ ├── ParamsExpected9.java │ │ │ │ └── ParamsExpectedException2.java │ │ │ │ ├── utils │ │ │ │ ├── TestClosure.java │ │ │ │ ├── IntBox.java │ │ │ │ ├── ByteBox.java │ │ │ │ ├── CharBox.java │ │ │ │ ├── LongBox.java │ │ │ │ ├── FloatBox.java │ │ │ │ ├── ShortBox.java │ │ │ │ ├── DoubleBox.java │ │ │ │ └── Utils.java │ │ │ │ ├── core │ │ │ │ └── SpecnazCoreDsl.java │ │ │ │ └── TestSettings.java │ │ └── resources │ │ │ └── specnaz-1.4.pom │ ├── specnaz-kotlin │ │ ├── build.gradle │ │ └── resources │ │ │ └── specnaz-kotlin-1.4.pom │ ├── specnaz-junit │ │ ├── build.gradle │ │ ├── src │ │ │ └── main │ │ │ │ └── java │ │ │ │ └── org │ │ │ │ └── specnaz │ │ │ │ ├── junit │ │ │ │ ├── rules │ │ │ │ │ ├── TestRuleSupplier.java │ │ │ │ │ └── MethodRuleSupplier.java │ │ │ │ ├── impl │ │ │ │ │ ├── JUnitDescUtils.java │ │ │ │ │ ├── JUnitFrameworkMethod.java │ │ │ │ │ └── TestCases2DescriptionsMap.java │ │ │ │ ├── SpecnazJUnit.java │ │ │ │ └── utils │ │ │ │ │ └── Utils.java │ │ │ │ └── params │ │ │ │ └── junit │ │ │ │ └── SpecnazParamsJUnit.java │ │ └── resources │ │ │ └── specnaz-junit-1.4.pom │ ├── specnaz-kotlin-testng │ │ ├── src │ │ │ └── main │ │ │ │ ├── resources │ │ │ │ └── META-INF │ │ │ │ │ └── services │ │ │ │ │ └── org.testng.ITestNGListener │ │ │ │ └── kotlin │ │ │ │ └── org │ │ │ │ └── specnaz │ │ │ │ └── kotlin │ │ │ │ ├── params │ │ │ │ └── testng │ │ │ │ │ ├── xSpecnazKotlinParamsTestNG.kt │ │ │ │ │ ├── SpecnazKotlinParamsTestNG.kt │ │ │ │ │ └── SpecnazKotlinParamsFactoryTestNG.kt │ │ │ │ └── testng │ │ │ │ ├── xSpecnazKotlinTestNG.kt │ │ │ │ ├── SpecnazKotlinAlterSuiteListener.kt │ │ │ │ ├── SpecnazKotlinTestNG.kt │ │ │ │ └── SpecnazKotlinFactoryTestNG.kt │ │ ├── build.gradle │ │ └── resources │ │ │ └── specnaz-kotlin-testng-1.4.pom │ ├── specnaz-testng │ │ ├── src │ │ │ ├── main │ │ │ │ ├── resources │ │ │ │ │ └── META-INF │ │ │ │ │ │ └── services │ │ │ │ │ │ └── org.testng.ITestNGListener │ │ │ │ └── java │ │ │ │ │ └── org │ │ │ │ │ └── specnaz │ │ │ │ │ └── testng │ │ │ │ │ ├── SpecnazMethodInterceptor.java │ │ │ │ │ ├── impl │ │ │ │ │ └── SharedAllsFixtures.java │ │ │ │ │ ├── SpecnazAlterSuiteListener.java │ │ │ │ │ └── SpecnazTests.java │ │ │ └── test │ │ │ │ └── java │ │ │ │ └── org │ │ │ │ └── specnaz │ │ │ │ └── testng │ │ │ │ └── SpecnazTestNgSpecWithBefores.java │ │ ├── build.gradle │ │ └── resources │ │ │ └── specnaz-testng-1.4.pom │ └── specnaz-kotlin-junit │ │ ├── build.gradle │ │ ├── src │ │ └── main │ │ │ └── kotlin │ │ │ └── org │ │ │ └── specnaz │ │ │ └── kotlin │ │ │ ├── params │ │ │ └── junit │ │ │ │ ├── SpecnazKotlinParamsJUnit.kt │ │ │ │ └── xSpecnazKotlinParamsJUnit.kt │ │ │ └── junit │ │ │ ├── xSpecnazKotlinJUnit.kt │ │ │ └── SpecnazKotlinJUnit.kt │ │ └── resources │ │ └── specnaz-kotlin-junit-1.4.pom └── examples │ ├── specnaz-junit-rules-examples │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ └── hello-world.yml │ │ │ └── java │ │ │ │ ├── dropwizard │ │ │ │ ├── Readme.md │ │ │ │ ├── api │ │ │ │ │ └── Saying.java │ │ │ │ ├── HelloWorldConfiguration.java │ │ │ │ ├── HelloWorldApplication.java │ │ │ │ └── resources │ │ │ │ │ └── HelloWorldResource.java │ │ │ │ └── a │ │ │ │ ├── Readme.md │ │ │ │ ├── DaoA.java │ │ │ │ └── ServiceA.java │ │ └── test │ │ │ └── java │ │ │ ├── spring │ │ │ ├── TestDaoA.java │ │ │ ├── TestSpringConfig.java │ │ │ └── Readme.md │ │ │ ├── mockito │ │ │ ├── Readme.md │ │ │ └── MockAnnotationMockitoRuleSpec.java │ │ │ ├── built_in_rules │ │ │ ├── TestNameRuleSpec.java │ │ │ └── ExpectedExceptionRuleSpec.java │ │ │ └── dropwizard │ │ │ └── HelloWorldIntegrationSpec.java │ ├── build.gradle │ └── Readme.md │ ├── specnaz-custom-dsl-example │ ├── build.gradle │ └── src │ │ ├── main │ │ └── java │ │ │ └── org │ │ │ └── specnaz │ │ │ └── examples │ │ │ └── custom_dsl │ │ │ └── given_when_then │ │ │ ├── ThensBuilder.java │ │ │ ├── GivenBuilder.java │ │ │ ├── standalone │ │ │ ├── SpecnazGivenWhenThenStandalone.java │ │ │ ├── GivenWhenThenCoreWrapper.java │ │ │ ├── GivenWhenThenRegistry.java │ │ │ └── GivenWhenThenStandaloneJUnitRunner.java │ │ │ ├── SpecnazGivenWhenThen.java │ │ │ └── GivenWhenThenBuilder.java │ │ └── test │ │ └── java │ │ ├── GivenWhenThenStackSpec.java │ │ └── standalone │ │ └── GivenWhenThenStandaloneStackSpec.java │ ├── specnaz-kotlin-examples │ ├── build.gradle │ └── src │ │ └── test │ │ └── kotlin │ │ ├── StackKotlinSpec.kt │ │ ├── FocusedKotlinSpec.kt │ │ └── KotlinParametrizedSpec.kt │ ├── specnaz-groovy-examples │ ├── build.gradle │ └── src │ │ └── test │ │ └── groovy │ │ └── StackGroovySpec.groovy │ ├── specnaz-java-examples │ ├── build.gradle │ └── src │ │ └── test │ │ └── java │ │ ├── StackSpec.java │ │ ├── FocusedSpec.java │ │ ├── MockitoExampleSpec.java │ │ └── ParametrizedSpec.java │ ├── specnaz-testng-examples │ ├── build.gradle │ └── src │ │ └── test │ │ ├── kotlin │ │ ├── ParametrizedKotlinSpec.kt │ │ └── StackKotlinSpec.kt │ │ └── java │ │ ├── ParametrizedSpec.java │ │ └── StackSpec.java │ └── Readme.md ├── .gitignore ├── docs └── img │ ├── specnaz-logo.png │ ├── stack-spec-result.png │ ├── testng-ide-report.png │ ├── parametrized-add-spec-result.png │ └── parametrized-sub-specification-result.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .travis.yml ├── License.txt ├── settings.gradle └── Changelog.md /src/main/specnaz/build.gradle: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | .idea/ 3 | build/ 4 | out/ 5 | -------------------------------------------------------------------------------- /docs/img/specnaz-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stvad/specnaz/master/docs/img/specnaz-logo.png -------------------------------------------------------------------------------- /src/main/specnaz-kotlin/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compile project(':src:main:specnaz') 3 | } 4 | -------------------------------------------------------------------------------- /docs/img/stack-spec-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stvad/specnaz/master/docs/img/stack-spec-result.png -------------------------------------------------------------------------------- /docs/img/testng-ide-report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stvad/specnaz/master/docs/img/testng-ide-report.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stvad/specnaz/master/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/main/resources/hello-world.yml: -------------------------------------------------------------------------------- 1 | template: Hello, %s! 2 | defaultName: Stranger 3 | -------------------------------------------------------------------------------- /docs/img/parametrized-add-spec-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stvad/specnaz/master/docs/img/parametrized-add-spec-result.png -------------------------------------------------------------------------------- /docs/img/parametrized-sub-specification-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Stvad/specnaz/master/docs/img/parametrized-sub-specification-result.png -------------------------------------------------------------------------------- /src/main/specnaz-junit/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compile project(':src:main:specnaz') 3 | 4 | provided "junit:junit:$junit_version" 5 | } 6 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-testng/src/main/resources/META-INF/services/org.testng.ITestNGListener: -------------------------------------------------------------------------------- 1 | org.specnaz.kotlin.testng.SpecnazKotlinAlterSuiteListener 2 | -------------------------------------------------------------------------------- /src/main/specnaz-testng/src/main/resources/META-INF/services/org.testng.ITestNGListener: -------------------------------------------------------------------------------- 1 | org.specnaz.testng.SpecnazAlterSuiteListener 2 | org.specnaz.testng.SpecnazMethodInterceptor 3 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/impl/Executable.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.impl; 2 | 3 | @FunctionalInterface 4 | public interface Executable { 5 | Throwable execute(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/specnaz-testng/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compile project(':src:main:specnaz') 3 | 4 | provided "org.testng:testng:$testng_version" 5 | } 6 | 7 | test { 8 | useTestNG() 9 | } 10 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/main/java/dropwizard/Readme.md: -------------------------------------------------------------------------------- 1 | This code is taken straight out of Dropwizard's 2 | [Getting Started Guide](http://www.dropwizard.io/1.2.2/docs/getting-started.html#tutorial). 3 | -------------------------------------------------------------------------------- /src/examples/specnaz-custom-dsl-example/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compile project(':src:main:specnaz-junit') 3 | compile "junit:junit:$junit_version" 4 | 5 | testCompile "org.assertj:assertj-core:$assertj_version" 6 | } 7 | -------------------------------------------------------------------------------- /src/examples/specnaz-kotlin-examples/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | testCompile project(":src:main:specnaz-kotlin-junit") 3 | testCompile "junit:junit:$junit_version" 4 | testCompile "org.assertj:assertj-core:$assertj_version" 5 | } 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-bin.zip 6 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-junit/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compile project(':src:main:specnaz') 3 | compile project(':src:main:specnaz-kotlin') 4 | compile project(':src:main:specnaz-junit') 5 | 6 | provided "junit:junit:$junit_version" 7 | } 8 | -------------------------------------------------------------------------------- /src/examples/specnaz-groovy-examples/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'groovy' 2 | 3 | dependencies { 4 | compile 'org.codehaus.groovy:groovy-all:2.3.11' 5 | 6 | testCompile project(':src:main:specnaz-junit') 7 | testCompile "junit:junit:$junit_version" 8 | } 9 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-testng/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compile project(':src:main:specnaz') 3 | compile project(':src:main:specnaz-kotlin') 4 | compile project(':src:main:specnaz-testng') 5 | 6 | provided "org.testng:testng:$testng_version" 7 | } 8 | -------------------------------------------------------------------------------- /src/examples/specnaz-java-examples/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | testCompile project(':src:main:specnaz-junit') 3 | testCompile "junit:junit:$junit_version" 4 | testCompile "org.assertj:assertj-core:$assertj_version" 5 | testCompile "org.mockito:mockito-core:2.8.47" 6 | } 7 | -------------------------------------------------------------------------------- /src/examples/specnaz-testng-examples/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compile project(':src:main:specnaz-testng') 3 | compile project(':src:main:specnaz-kotlin-testng') 4 | 5 | testCompile "org.testng:testng:$testng_version" 6 | } 7 | 8 | test { 9 | useTestNG() 10 | } 11 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/impl/SpecsRegistryViolation.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.impl; 2 | 3 | public class SpecsRegistryViolation extends Exception { 4 | public SpecsRegistryViolation(String format, Object... args) { 5 | super(String.format(format, args)); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/main/java/a/Readme.md: -------------------------------------------------------------------------------- 1 | An extremely simple example of a 'service' ([ServiceA](ServiceA.java)) with one dependency 2 | ([DaoA](DaoA.java)). 3 | 4 | Used in the [Mockito](../../../test/java/mockito) and [Spring](../../../test/java/spring) 5 | JUnit Rules examples. 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | - oraclejdk9 5 | - openjdk8 6 | before_cache: 7 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 8 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ 9 | cache: 10 | directories: 11 | - $HOME/.gradle/caches/ 12 | - $HOME/.gradle/wrapper/ 13 | -------------------------------------------------------------------------------- /src/examples/specnaz-custom-dsl-example/src/main/java/org/specnaz/examples/custom_dsl/given_when_then/ThensBuilder.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.examples.custom_dsl.given_when_then; 2 | 3 | import org.specnaz.utils.TestClosure; 4 | 5 | public interface ThensBuilder { 6 | void then(String description, TestClosure testBody); 7 | } 8 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/main/java/a/DaoA.java: -------------------------------------------------------------------------------- 1 | package a; 2 | 3 | /** 4 | * A dependency of {@link ServiceA}. 5 | * 6 | * @see #getA 7 | */ 8 | public interface DaoA { 9 | /** 10 | * Used in {@link ServiceA#findA}. 11 | * 12 | * @return String 13 | */ 14 | String getA(); 15 | } 16 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/test/java/spring/TestDaoA.java: -------------------------------------------------------------------------------- 1 | package spring; 2 | 3 | import a.DaoA; 4 | 5 | /** 6 | * A test implementation of {@link DaoA}. 7 | * 8 | * @see #getA 9 | */ 10 | public final class TestDaoA implements DaoA { 11 | /** 12 | * @return {@code "TestDaoA"} 13 | */ 14 | @Override 15 | public String getA() { 16 | return "TestDaoA"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/specnaz/resources/specnaz-1.4.pom: -------------------------------------------------------------------------------- 1 | 5 | 4.0.0 6 | 7 | org.specnaz 8 | specnaz 9 | 1.4 10 | 11 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/impl/SinglePositiveTestCase.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.utils.TestClosure; 5 | 6 | public final class SinglePositiveTestCase extends SingleTestCase { 7 | public SinglePositiveTestCase(TestSettings testSettings, String description, TestClosure testBody, 8 | TestCaseType testCaseType) { 9 | super(testSettings, description, testBody, testCaseType); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/specnaz-junit/src/main/java/org/specnaz/junit/rules/TestRuleSupplier.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.junit.rules; 2 | 3 | import org.junit.rules.TestRule; 4 | 5 | /** 6 | * A {@link FunctionalInterface} used as the parameter to the 7 | * {@link Rule#of(TestRuleSupplier)} static factory method. 8 | * 9 | * @param 10 | * the type of {@link TestRule} returned by this Supplier 11 | */ 12 | @FunctionalInterface 13 | public interface TestRuleSupplier { 14 | T get(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/specnaz-junit/src/main/java/org/specnaz/junit/impl/JUnitDescUtils.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.junit.impl; 2 | 3 | import org.junit.runner.Description; 4 | 5 | import java.lang.annotation.Annotation; 6 | 7 | public class JUnitDescUtils { 8 | public static Description makeTestDesc(String description, Description parentDescription, 9 | Annotation... annotations) { 10 | return Description.createTestDescription(parentDescription.getDisplayName(), description, annotations); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/specnaz-junit/src/main/java/org/specnaz/junit/rules/MethodRuleSupplier.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.junit.rules; 2 | 3 | import org.junit.rules.MethodRule; 4 | 5 | /** 6 | * A {@link FunctionalInterface} used as the parameter to the 7 | * {@link Rule#of(MethodRuleSupplier)} static factory method. 8 | * 9 | * @param 10 | * the type of {@link MethodRule} returned by this Supplier 11 | */ 12 | @FunctionalInterface 13 | public interface MethodRuleSupplier { 14 | T get(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/RunnableParams1.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link Runnable} for parametrized 5 | * sub-specifications taking one parameter. 6 | * 7 | * @see #invoke(P) 8 | * @see ParamsSpecBuilder#describes(String, RunnableParams1) 9 | */ 10 | @FunctionalInterface 11 | public interface RunnableParams1

{ 12 | /** 13 | * The abstract method of the {@link FunctionalInterface}. 14 | * 15 | * @param p the parameter 16 | */ 17 | void invoke(P p); 18 | } 19 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | Copyright 2016 Adam Ruka 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'specnaz-all' 2 | 3 | include 'src:main:specnaz', 4 | 'src:main:specnaz-junit', 5 | 'src:main:specnaz-kotlin', 6 | 'src:main:specnaz-kotlin-junit', 7 | 'src:main:specnaz-testng', 8 | 'src:main:specnaz-kotlin-testng', 9 | 'src:examples:specnaz-java-examples', 10 | 'src:examples:specnaz-junit-rules-examples', 11 | 'src:examples:specnaz-kotlin-examples', 12 | 'src:examples:specnaz-groovy-examples', 13 | 'src:examples:specnaz-testng-examples', 14 | 'src:examples:specnaz-custom-dsl-example' 15 | -------------------------------------------------------------------------------- /src/main/specnaz-junit/src/main/java/org/specnaz/junit/SpecnazJUnit.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.junit; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.junit.runner.Runner; 5 | import org.specnaz.Specnaz; 6 | 7 | /** 8 | * A utility class that implements the {@link Specnaz} interface 9 | * and declares {@link SpecnazJUnitRunner} as the JUnit test {@link Runner} 10 | * with the {@link RunWith} annotation. 11 | * Useful in cases where your test class doesn't have to extend any particular class. 12 | */ 13 | @RunWith(SpecnazJUnitRunner.class) 14 | public abstract class SpecnazJUnit implements Specnaz { 15 | } 16 | -------------------------------------------------------------------------------- /src/examples/specnaz-custom-dsl-example/src/main/java/org/specnaz/examples/custom_dsl/given_when_then/GivenBuilder.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.examples.custom_dsl.given_when_then; 2 | 3 | import org.specnaz.utils.TestClosure; 4 | 5 | import java.util.function.Consumer; 6 | 7 | public interface GivenBuilder { 8 | default void given(String description, Runnable closure) { 9 | given(description, () -> {}, closure); 10 | } 11 | 12 | void given(String description, TestClosure action, Runnable closure); 13 | 14 | void when(String description, TestClosure action, Consumer thens); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedSubgroupInstance.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | 5 | public final class ParametrizedSubgroupInstance { 6 | public final String description; 7 | public final Runnable specClosure; 8 | public final TestCaseType testCaseType; 9 | 10 | public ParametrizedSubgroupInstance(String description, Runnable specClosure, TestCaseType testCaseType) { 11 | this.description = description; 12 | this.specClosure = specClosure; 13 | this.testCaseType = testCaseType; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/RunnableParams2.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link Runnable} for parametrized 5 | * sub-specifications taking 2 parameters. 6 | * 7 | * @see #invoke(P1, P2) 8 | * @see ParamsSpecBuilder#describes(String, RunnableParams2) 9 | */ 10 | @FunctionalInterface 11 | public interface RunnableParams2 { 12 | /** 13 | * The abstract method of the {@link FunctionalInterface}. 14 | * 15 | * @param param1 first parameter 16 | * @param param2 second parameter 17 | */ 18 | void invoke(P1 param1, P2 param2); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/impl/TestCaseType.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.impl; 2 | 3 | public enum TestCaseType { 4 | REGULAR, 5 | FOCUSED, 6 | IGNORED; 7 | 8 | public TestCaseType descendantTestType(TestCaseType testCaseType) { 9 | switch (this) { 10 | case REGULAR: 11 | return testCaseType; 12 | case FOCUSED: 13 | return testCaseType == REGULAR 14 | ? FOCUSED 15 | : testCaseType; 16 | case IGNORED: 17 | default: 18 | return IGNORED; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/examples/specnaz-testng-examples/src/test/kotlin/ParametrizedKotlinSpec.kt: -------------------------------------------------------------------------------- 1 | import org.specnaz.kotlin.params.testng.SpecnazKotlinParamsFactoryTestNG 2 | import org.testng.annotations.Test 3 | 4 | /** 5 | * Example of a parametrized Kotlin spec, 6 | * running using TestNG as the execution engine. 7 | */ 8 | @Test 9 | class ParametrizedKotlinSpec : SpecnazKotlinParamsFactoryTestNG { init { 10 | describes("A parametrized Kotlin spec") { 11 | it.shouldThrow("when parsing '%1' as an Int") { str -> 12 | Integer.parseInt(str) 13 | }.provided("cafe", "BABE").withoutCause() 14 | } 15 | }} 16 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/impl/SpecDescriptor.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.impl; 2 | 3 | import org.specnaz.core.CoreDslBuilder; 4 | 5 | import java.util.function.Consumer; 6 | 7 | public final class SpecDescriptor { 8 | public final String description; 9 | public final boolean ignoredTestGroup; 10 | public final Consumer specClosure; 11 | 12 | public SpecDescriptor(String description, boolean ignoredTestGroup, Consumer specClosure) { 13 | this.description = description; 14 | this.ignoredTestGroup = ignoredTestGroup; 15 | this.specClosure = specClosure; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/test/java/spring/TestSpringConfig.java: -------------------------------------------------------------------------------- 1 | package spring; 2 | 3 | import a.DaoA; 4 | import a.ServiceA; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * A test Spring configuration, 10 | * wiring up {@link TestDaoA} as the implementation of {@link DaoA}. 11 | */ 12 | @Configuration 13 | public class TestSpringConfig { 14 | @Bean 15 | public DaoA daoA() { 16 | return new TestDaoA(); 17 | } 18 | 19 | @Bean 20 | public ServiceA serviceA(DaoA daoA) { 21 | return new ServiceA(daoA); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/test/java/mockito/Readme.md: -------------------------------------------------------------------------------- 1 | Demonstrates using [Mockito's JUnit Rule](https://static.javadoc.io/org.mockito/mockito-core/1.10.19/org/mockito/junit/MockitoRule.html) in Specnaz. 2 | 3 | The integration is straightforward, except for one detail: 4 | if you use the [@InjectMocks](https://static.javadoc.io/org.mockito/mockito-core/2.13.0/org/mockito/InjectMocks.html) annotation, 5 | you need to make sure to re-set 6 | (that is, assign to `null`) 7 | all fields annotated with that after each test - 8 | otherwise, they won't be injected with fresh mock instances again. 9 | See [this test](InjectMocksAnnotationMockitoRuleSpec.java) for details. 10 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/RunnableParams3.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link Runnable} for parametrized 5 | * sub-specifications taking 3 parameters. 6 | * 7 | * @see #invoke(P1, P2, P3) 8 | * @see ParamsSpecBuilder#describes(String, RunnableParams3) 9 | */ 10 | @FunctionalInterface 11 | public interface RunnableParams3 { 12 | /** 13 | * The abstract method of the {@link FunctionalInterface}. 14 | * 15 | * @param param1 first parameter 16 | * @param param2 second parameter 17 | * @param param3 third parameter 18 | */ 19 | void invoke(P1 param1, P2 param2, P3 param3); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/impl/ExecutableTestCase.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.impl; 2 | 3 | public final class ExecutableTestCase { 4 | public final SingleTestCase testCase; 5 | private final Executable executable; 6 | 7 | public ExecutableTestCase(SingleTestCase testCase) { 8 | this(testCase, null); 9 | } 10 | 11 | public ExecutableTestCase(SingleTestCase testCase, Executable executable) { 12 | this.testCase = testCase; 13 | this.executable = executable; 14 | } 15 | 16 | public boolean isIgnored() { 17 | return executable == null; 18 | } 19 | 20 | public Throwable execute() { 21 | return executable.execute(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-testng/src/main/kotlin/org/specnaz/kotlin/params/testng/xSpecnazKotlinParamsTestNG.kt: -------------------------------------------------------------------------------- 1 | package org.specnaz.kotlin.params.testng 2 | 3 | import org.specnaz.kotlin.params.KotlinParamsSpecBuilder 4 | import org.testng.annotations.Test 5 | 6 | /** 7 | * The parametrized equivalent of [org.specnaz.kotlin.testng.xSpecnazKotlinTestNG]. 8 | * 9 | * @see SpecnazKotlinParamsTestNG 10 | * @see org.specnaz.kotlin.params.SpecnazKotlinParams.xdescribes 11 | */ 12 | @Test 13 | abstract class xSpecnazKotlinParamsTestNG(description: String, 14 | specClosure: (KotlinParamsSpecBuilder) -> Unit) : SpecnazKotlinParamsFactoryTestNG { 15 | init { 16 | xdescribes(description, specClosure) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/main/java/a/ServiceA.java: -------------------------------------------------------------------------------- 1 | package a; 2 | 3 | /** 4 | * An example 'service'. 5 | * It has one 'business' method 6 | * ({@link #findA}) and one dependency 7 | * (on the {@link DaoA} interface). 8 | * 9 | * @see #findA 10 | */ 11 | public final class ServiceA { 12 | private final DaoA daoA; 13 | 14 | public ServiceA(DaoA daoA) { 15 | this.daoA = daoA; 16 | } 17 | 18 | /** 19 | * The 'business' method of {@link ServiceA}. 20 | * 21 | * @return the String {@code "ServiceA:"} 22 | * concatenated with whatever {@link DaoA#getA} returns 23 | */ 24 | public String findA() { 25 | return "ServiceA:" + daoA.getA(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/specnaz-junit/src/main/java/org/specnaz/params/junit/SpecnazParamsJUnit.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.junit; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.specnaz.junit.SpecnazJUnitRunner; 5 | import org.specnaz.params.SpecnazParams; 6 | 7 | /** 8 | * The parametrized equivalent of {@link org.specnaz.junit.SpecnazJUnit}. 9 | * Implements the {@link SpecnazParams} interface and declares 10 | * {@link SpecnazJUnitRunner} as the JUnit {@link org.junit.runner.Runner} 11 | * with the {@link RunWith} annotation. 12 | * Useful in cases when your test class doesn't need to extend any particular class. 13 | */ 14 | @RunWith(SpecnazJUnitRunner.class) 15 | public abstract class SpecnazParamsJUnit implements SpecnazParams { 16 | } 17 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/RunnableParams4.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link Runnable} for parametrized 5 | * sub-specifications taking 4 parameters. 6 | * 7 | * @see #invoke(P1, P2, P3, P4) 8 | * @see ParamsSpecBuilder#describes(String, RunnableParams4) 9 | */ 10 | @FunctionalInterface 11 | public interface RunnableParams4 { 12 | /** 13 | * The abstract method of the {@link FunctionalInterface}. 14 | * 15 | * @param param1 first parameter 16 | * @param param2 second parameter 17 | * @param param3 third parameter 18 | * @param param4 fourth parameter 19 | */ 20 | void invoke(P1 param1, P2 param2, P3 param3, P4 param4); 21 | } 22 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/build.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | spring_version = '5.0.2.RELEASE' 3 | dropwizard_version = '1.2.2' 4 | } 5 | 6 | dependencies { 7 | compile "io.dropwizard:dropwizard-core:$dropwizard_version" 8 | 9 | testCompile project(':src:main:specnaz-junit') 10 | testCompile "junit:junit:$junit_version" 11 | testCompile "org.assertj:assertj-core:$assertj_version" 12 | testCompile "org.mockito:mockito-core:1.10.19" 13 | testCompile "org.springframework:spring-beans:$spring_version" 14 | testCompile "org.springframework:spring-context:$spring_version" 15 | testCompile "org.springframework:spring-test:$spring_version" 16 | testCompile "io.dropwizard:dropwizard-testing:$dropwizard_version" 17 | } 18 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/utils/TestClosure.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.utils; 2 | 3 | /** 4 | * A simple {@link FunctionalInterface}, similar to 5 | * {@link Runnable}, except it allows you to throw any 6 | * Exception in the body of the method. 7 | * Used for lifecycle callbacks ({@code begins/ends}) 8 | * and test bodies. 9 | * 10 | * @see #invoke 11 | */ 12 | @FunctionalInterface 13 | public interface TestClosure { 14 | /** 15 | * Invokes the callback. 16 | * 17 | * @throws Exception you can safely throw any Exception 18 | * in the method body - it will be caught and processed 19 | * by the library (usually resulting in a test failure) 20 | */ 21 | void invoke() throws Exception; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/TestClosureParams1.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link org.specnaz.utils.TestClosure} for 5 | * parametrized tests taking one parameter. 6 | * 7 | * @see #invoke 8 | * @see org.specnaz.utils.TestClosure 9 | * @see ParamsSpecBuilder#should(String, TestClosureParams1) 10 | * @see ParamsSpecBuilder#shouldThrow(Class, String, TestClosureParams1) 11 | */ 12 | @FunctionalInterface 13 | public interface TestClosureParams1

{ 14 | /** 15 | * The abstract method of the {@link FunctionalInterface}. 16 | * 17 | * @param p the parameter 18 | * @throws Exception can safely throw any Exception 19 | */ 20 | void invoke(P p) throws Exception; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedSubgroup1.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.RunnableParams1; 5 | 6 | import java.util.List; 7 | 8 | public final class ParametrizedSubgroup1

extends AbstractParametrizedSubgroup { 9 | private final RunnableParams1

specClosure; 10 | 11 | public ParametrizedSubgroup1(String description, RunnableParams1

specClosure, TestCaseType testCaseType) { 12 | super(description, testCaseType); 13 | this.specClosure = specClosure; 14 | } 15 | 16 | @Override 17 | protected Runnable toSpecClosure(List paramsSet) { 18 | return () -> specClosure.invoke((P) paramsSet.get(0)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/RunnableParams5.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link Runnable} for parametrized 5 | * sub-specifications taking 5 parameters. 6 | * 7 | * @see #invoke(P1, P2, P3, P4, P5) 8 | * @see ParamsSpecBuilder#describes(String, RunnableParams5) 9 | */ 10 | @FunctionalInterface 11 | public interface RunnableParams5 { 12 | /** 13 | * The abstract method of the {@link FunctionalInterface}. 14 | * 15 | * @param param1 first parameter 16 | * @param param2 second parameter 17 | * @param param3 third parameter 18 | * @param param4 fourth parameter 19 | * @param param5 fifth parameter 20 | */ 21 | void invoke(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedSubgroup2.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.RunnableParams2; 5 | 6 | import java.util.List; 7 | 8 | public final class ParametrizedSubgroup2 extends AbstractParametrizedSubgroup { 9 | private final RunnableParams2 specClosure; 10 | 11 | public ParametrizedSubgroup2(String description, RunnableParams2 specClosure, 12 | TestCaseType testCaseType) { 13 | super(description, testCaseType); 14 | this.specClosure = specClosure; 15 | } 16 | 17 | @Override 18 | protected Runnable toSpecClosure(List paramsSet) { 19 | return () -> specClosure.invoke((P1) paramsSet.get(0), (P2) paramsSet.get(1)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/TestClosureParams2.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link org.specnaz.utils.TestClosure} for 5 | * parametrized tests taking 2 parameters. 6 | * 7 | * @see #invoke 8 | * @see org.specnaz.utils.TestClosure 9 | * @see ParamsSpecBuilder#should(String, TestClosureParams2) 10 | * @see ParamsSpecBuilder#shouldThrow(Class, String, TestClosureParams2) 11 | */ 12 | @FunctionalInterface 13 | public interface TestClosureParams2 { 14 | /** 15 | * The abstract method of the {@link FunctionalInterface}. 16 | * 17 | * @param param1 the first parameter 18 | * @param param2 the second parameter 19 | * @throws Exception can safely throw any Exception 20 | */ 21 | void invoke(P1 param1, P2 param2) throws Exception; 22 | } 23 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/test/java/built_in_rules/TestNameRuleSpec.java: -------------------------------------------------------------------------------- 1 | package built_in_rules; 2 | 3 | import org.junit.rules.TestName; 4 | import org.specnaz.junit.SpecnazJUnit; 5 | import org.specnaz.junit.rules.Rule; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | /** 10 | * An example of using Specnaz with the built-in {@link TestName} Rule. 11 | */ 12 | public class TestNameRuleSpec extends SpecnazJUnit { 13 | public Rule testName = Rule.of(() -> new TestName()); 14 | 15 | { 16 | describes("Using the TestName JUnit Rule in Specnaz", it -> { 17 | it.should("correctly set the test name", () -> { 18 | assertThat(testName.r().getMethodName()).isEqualTo("should correctly set the test name"); 19 | }); 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/Params2.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * A simple tuple class holding 2 values. 5 | * You use it to provide parameters to the {@link ParamsExpected2} 6 | * and {@link ParamsExpectedException2} classes. 7 | */ 8 | public final class Params2 { 9 | /** 10 | * Factory method. 11 | * 12 | * @param param1 first parameter 13 | * @param param2 second parameter 14 | * @return a new instance of the {@link Params2} class 15 | */ 16 | public static Params2 p2(P1 param1, P2 param2) { 17 | return new Params2<>(param1, param2); 18 | } 19 | 20 | public final P1 _1; 21 | public final P2 _2; 22 | 23 | private Params2(P1 param1, P2 param2) { 24 | _1 = param1; 25 | _2 = param2; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-junit/src/main/kotlin/org/specnaz/kotlin/params/junit/SpecnazKotlinParamsJUnit.kt: -------------------------------------------------------------------------------- 1 | package org.specnaz.kotlin.params.junit 2 | 3 | import org.junit.runner.RunWith 4 | import org.specnaz.kotlin.junit.SpecnazKotlinJUnitRunner 5 | import org.specnaz.kotlin.params.KotlinParamsSpecBuilder 6 | import org.specnaz.kotlin.params.SpecnazKotlinParams 7 | 8 | /** 9 | * The equivalent of [org.specnaz.params.junit.SpecnazParamsJUnit] for Kotlin, 10 | * and the parametrized version of [org.specnaz.kotlin.junit.SpecnazKotlinJUnit]. 11 | */ 12 | @RunWith(SpecnazKotlinJUnitRunner::class) 13 | abstract class SpecnazKotlinParamsJUnit(description: String, 14 | specClosure: (KotlinParamsSpecBuilder) -> Unit) : 15 | SpecnazKotlinParams { 16 | init { 17 | this.describes(description, specClosure) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/RunnableParams6.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link Runnable} for parametrized 5 | * sub-specifications taking 6 parameters. 6 | * 7 | * @see #invoke(P1, P2, P3, P4, P5, P6) 8 | * @see ParamsSpecBuilder#describes(String, RunnableParams6) 9 | */ 10 | @FunctionalInterface 11 | public interface RunnableParams6 { 12 | /** 13 | * The abstract method of the {@link FunctionalInterface}. 14 | * 15 | * @param param1 first parameter 16 | * @param param2 second parameter 17 | * @param param3 third parameter 18 | * @param param4 fourth parameter 19 | * @param param5 fifth parameter 20 | * @param param6 sixth parameter 21 | */ 22 | void invoke(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6); 23 | } 24 | -------------------------------------------------------------------------------- /src/examples/specnaz-custom-dsl-example/src/main/java/org/specnaz/examples/custom_dsl/given_when_then/standalone/SpecnazGivenWhenThenStandalone.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.examples.custom_dsl.given_when_then.standalone; 2 | 3 | import org.specnaz.examples.custom_dsl.given_when_then.GivenBuilder; 4 | 5 | import java.util.function.Consumer; 6 | 7 | public interface SpecnazGivenWhenThenStandalone { 8 | default void given(String description, Consumer specClosure) { 9 | try { 10 | GivenWhenThenRegistry.add(this, "Given " + description, specClosure); 11 | } catch (IllegalArgumentException e) { 12 | throw new IllegalStateException("SpecnazGivenWhenThenStandalone.given() was called multiple times in the " + 13 | "no-argument constructor of " + this.getClass().getSimpleName()); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedSubgroup3.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.RunnableParams3; 5 | 6 | import java.util.List; 7 | 8 | public final class ParametrizedSubgroup3 extends AbstractParametrizedSubgroup { 9 | private final RunnableParams3 specClosure; 10 | 11 | public ParametrizedSubgroup3(String description, RunnableParams3 specClosure, 12 | TestCaseType testCaseType) { 13 | super(description, testCaseType); 14 | this.specClosure = specClosure; 15 | } 16 | 17 | @Override 18 | protected Runnable toSpecClosure(List paramsSet) { 19 | return () -> specClosure.invoke((P1) paramsSet.get(0), (P2) paramsSet.get(1), 20 | (P3) paramsSet.get(2)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/main/java/dropwizard/api/Saying.java: -------------------------------------------------------------------------------- 1 | package dropwizard.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import org.hibernate.validator.constraints.Length; 5 | 6 | /** 7 | * Taken from here. 8 | */ 9 | public class Saying { 10 | private long id; 11 | 12 | @Length(max = 3) 13 | private String content; 14 | 15 | public Saying() { 16 | // Jackson deserialization 17 | } 18 | 19 | public Saying(long id, String content) { 20 | this.id = id; 21 | this.content = content; 22 | } 23 | 24 | @JsonProperty 25 | public long getId() { 26 | return id; 27 | } 28 | 29 | @JsonProperty 30 | public String getContent() { 31 | return content; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-testng/src/main/kotlin/org/specnaz/kotlin/params/testng/SpecnazKotlinParamsTestNG.kt: -------------------------------------------------------------------------------- 1 | package org.specnaz.kotlin.params.testng 2 | 3 | import org.specnaz.kotlin.params.KotlinParamsSpecBuilder 4 | import org.testng.annotations.Test 5 | 6 | /** 7 | * The parametrized equivalent of [org.specnaz.kotlin.testng.SpecnazKotlinTestNG]. 8 | * You use it exactly like [org.specnaz.kotlin.testng.SpecnazKotlinTestNG]. 9 | * 10 | * @see org.specnaz.kotlin.testng.SpecnazKotlinTestNG 11 | * @see SpecnazKotlinParamsFactoryTestNG 12 | * @see org.specnaz.kotlin.params.SpecnazKotlinParams 13 | * @see xSpecnazKotlinParamsTestNG 14 | */ 15 | @Test 16 | abstract class SpecnazKotlinParamsTestNG(description: String, 17 | specClosure: (KotlinParamsSpecBuilder) -> Unit) : SpecnazKotlinParamsFactoryTestNG { 18 | init { 19 | describes(description, specClosure) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-junit/src/main/kotlin/org/specnaz/kotlin/params/junit/xSpecnazKotlinParamsJUnit.kt: -------------------------------------------------------------------------------- 1 | package org.specnaz.kotlin.params.junit 2 | 3 | import org.junit.runner.RunWith 4 | import org.specnaz.kotlin.junit.SpecnazKotlinJUnitRunner 5 | import org.specnaz.kotlin.params.KotlinParamsSpecBuilder 6 | import org.specnaz.kotlin.params.SpecnazKotlinParams 7 | 8 | /** 9 | * The parametrized equivalent of [org.specnaz.kotlin.junit.xSpecnazKotlinJUnit]. 10 | * Allows you to ignore an entire parametrized spec extending from 11 | * [SpecnazKotlinParamsJUnit]. 12 | */ 13 | @RunWith(SpecnazKotlinJUnitRunner::class) 14 | abstract class xSpecnazKotlinParamsJUnit(description: String, 15 | specClosure: (KotlinParamsSpecBuilder) -> Unit) : 16 | SpecnazKotlinParams { 17 | init { 18 | this.xdescribes(description, specClosure) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/TestClosureParams3.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link org.specnaz.utils.TestClosure} for 5 | * parametrized tests taking 3 parameters. 6 | * 7 | * @see #invoke 8 | * @see org.specnaz.utils.TestClosure 9 | * @see ParamsSpecBuilder#should(String, TestClosureParams3) 10 | * @see ParamsSpecBuilder#shouldThrow(Class, String, TestClosureParams3) 11 | */ 12 | @FunctionalInterface 13 | public interface TestClosureParams3 { 14 | /** 15 | * The abstract method of the {@link FunctionalInterface}. 16 | * 17 | * @param param1 the first parameter 18 | * @param param2 the second parameter 19 | * @param param3 the third parameter 20 | * @throws Exception can safely throw any Exception 21 | */ 22 | void invoke(P1 param1, P2 param2, P3 param3) throws Exception; 23 | } 24 | -------------------------------------------------------------------------------- /src/examples/specnaz-testng-examples/src/test/java/ParametrizedSpec.java: -------------------------------------------------------------------------------- 1 | import org.specnaz.params.testng.SpecnazParamsFactoryTestNG; 2 | import org.testng.annotations.Test; 3 | 4 | import static java.lang.String.format; 5 | 6 | /** 7 | * An example of a parametrized Specnaz spec, 8 | * running using TestNG as the execution engine. 9 | */ 10 | @Test 11 | public class ParametrizedSpec implements SpecnazParamsFactoryTestNG {{ 12 | describes("A parametrized spec", it -> { 13 | it.describes("with '%1' as the argument", (String str) -> { 14 | it.shouldThrow(NumberFormatException.class, 15 | format("when trying to parse '%s' as an Int with radix %%1", str), (Integer radix) -> { 16 | Integer.parseInt(str, radix); 17 | }).provided(8, 10) 18 | .withMessageContaining(str); 19 | }).provided("cafe", "G"); 20 | }); 21 | }} 22 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/RunnableParams7.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link Runnable} for parametrized 5 | * sub-specifications taking 7 parameters. 6 | * 7 | * @see #invoke 8 | * @see ParamsSpecBuilder#describes(String, RunnableParams7) 9 | */ 10 | @FunctionalInterface 11 | public interface RunnableParams7 { 12 | /** 13 | * The abstract method of the {@link FunctionalInterface}. 14 | * 15 | * @param param1 first parameter 16 | * @param param2 second parameter 17 | * @param param3 third parameter 18 | * @param param4 fourth parameter 19 | * @param param5 fifth parameter 20 | * @param param6 sixth parameter 21 | * @param param7 seventh parameter 22 | */ 23 | void invoke(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6, P7 param7); 24 | } 25 | -------------------------------------------------------------------------------- /src/examples/specnaz-groovy-examples/src/test/groovy/StackGroovySpec.groovy: -------------------------------------------------------------------------------- 1 | import org.specnaz.junit.SpecnazJUnit 2 | 3 | public class StackGroovySpec extends SpecnazJUnit {{ 4 | describes("A Stack") { 5 | Stack stack = new Stack<>() 6 | 7 | it.should("be empty when first created") { 8 | assert stack.isEmpty() 9 | } 10 | 11 | it.endsEach { 12 | stack = new Stack<>() 13 | } 14 | 15 | it.describes("with 10 and 20 pushed on it") { -> 16 | it.beginsEach { 17 | stack.push(10) 18 | stack.push(20) 19 | } 20 | 21 | it.should("have size equal to 2") { 22 | assert stack.size() == 2 23 | } 24 | 25 | it.should("have 20 as the top element") { 26 | assert stack.peek() == 20 27 | } 28 | } 29 | } 30 | }} 31 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedSubgroup4.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.RunnableParams4; 5 | 6 | import java.util.List; 7 | 8 | public final class ParametrizedSubgroup4 extends AbstractParametrizedSubgroup { 9 | private final RunnableParams4 specClosure; 10 | 11 | public ParametrizedSubgroup4(String description, RunnableParams4 specClosure, 12 | TestCaseType testCaseType) { 13 | super(description, testCaseType); 14 | this.specClosure = specClosure; 15 | } 16 | 17 | @Override 18 | protected Runnable toSpecClosure(List paramsSet) { 19 | return () -> specClosure.invoke((P1) paramsSet.get(0), (P2) paramsSet.get(1), 20 | (P3) paramsSet.get(2), (P4) paramsSet.get(3)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedPositiveTest1.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.impl.TestCaseType; 5 | import org.specnaz.params.TestClosureParams1; 6 | import org.specnaz.utils.TestClosure; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedPositiveTest1

extends 11 | AbstractParametrizedPositiveTest { 12 | private final TestClosureParams1

testBody; 13 | 14 | public ParametrizedPositiveTest1(TestSettings testSettings, 15 | String description, TestClosureParams1

testBody, TestCaseType testCaseType) { 16 | super(testSettings, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure1(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/AbstractParametrizedPositiveTest.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.impl.SinglePositiveTestCase; 5 | import org.specnaz.impl.SingleTestCase; 6 | import org.specnaz.impl.TestCaseType; 7 | 8 | import java.util.List; 9 | 10 | public abstract class AbstractParametrizedPositiveTest extends AbstractParametrizedTest { 11 | public final TestSettings testSettings; 12 | 13 | AbstractParametrizedPositiveTest(TestSettings testSettings, String description, TestCaseType testCaseType) { 14 | super(description, testCaseType); 15 | this.testSettings = testSettings; 16 | } 17 | 18 | @Override 19 | protected SingleTestCase testCase(List params) { 20 | return new SinglePositiveTestCase(testSettings, 21 | formatDesc(params), toTestClosure(params), testCaseType); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedPositiveTest2.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.impl.TestCaseType; 5 | import org.specnaz.params.TestClosureParams2; 6 | import org.specnaz.utils.TestClosure; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedPositiveTest2 extends 11 | AbstractParametrizedPositiveTest { 12 | private final TestClosureParams2 testBody; 13 | 14 | public ParametrizedPositiveTest2(TestSettings testSettings, 15 | String description, TestClosureParams2 testBody, TestCaseType testCaseType) { 16 | super(testSettings, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure2(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/examples/specnaz-kotlin-examples/src/test/kotlin/StackKotlinSpec.kt: -------------------------------------------------------------------------------- 1 | import org.junit.Assert 2 | import org.specnaz.kotlin.junit.SpecnazKotlinJUnit 3 | import java.util.Stack 4 | 5 | /** 6 | * This is the example spec from the Readme file. 7 | */ 8 | class StackKotlinSpec : SpecnazKotlinJUnit("A Stack", { 9 | var stack = Stack() 10 | 11 | it.endsEach { 12 | stack = Stack() 13 | } 14 | 15 | it.should("be empty when first created") { 16 | Assert.assertTrue(stack.isEmpty()) 17 | } 18 | 19 | it.describes("with 10 and 20 pushed on it") { 20 | it.beginsEach { 21 | stack.push(10) 22 | stack.push(20) 23 | } 24 | 25 | it.should("have size equal to 2") { 26 | Assert.assertEquals(2, stack.size) 27 | } 28 | 29 | it.should("have 20 as the top element") { 30 | Assert.assertEquals(20, stack.peek()) 31 | } 32 | } 33 | }) 34 | -------------------------------------------------------------------------------- /src/main/specnaz-junit/resources/specnaz-junit-1.4.pom: -------------------------------------------------------------------------------- 1 | 5 | 4.0.0 6 | 7 | org.specnaz 8 | specnaz-junit 9 | 1.4 10 | 11 | 12 | 13 | org.specnaz 14 | specnaz 15 | 1.4 16 | 17 | 18 | 19 | junit 20 | junit 21 | 4.12 22 | provided 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedSubgroup5.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.RunnableParams5; 5 | 6 | import java.util.List; 7 | 8 | public final class ParametrizedSubgroup5 extends AbstractParametrizedSubgroup { 9 | private final RunnableParams5 specClosure; 10 | 11 | public ParametrizedSubgroup5(String description, 12 | RunnableParams5 specClosure, TestCaseType testCaseType) { 13 | super(description, testCaseType); 14 | this.specClosure = specClosure; 15 | } 16 | 17 | @Override 18 | protected Runnable toSpecClosure(List paramsSet) { 19 | return () -> specClosure.invoke((P1) paramsSet.get(0), (P2) paramsSet.get(1), 20 | (P3) paramsSet.get(2), (P4) paramsSet.get(3), (P5) paramsSet.get(4)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/RunnableParams8.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link Runnable} for parametrized 5 | * sub-specifications taking 8 parameters. 6 | * 7 | * @see #invoke 8 | * @see ParamsSpecBuilder#describes(String, RunnableParams8) 9 | */ 10 | @FunctionalInterface 11 | public interface RunnableParams8 { 12 | /** 13 | * The abstract method of the {@link FunctionalInterface}. 14 | * 15 | * @param param1 first parameter 16 | * @param param2 second parameter 17 | * @param param3 third parameter 18 | * @param param4 fourth parameter 19 | * @param param5 fifth parameter 20 | * @param param6 sixth parameter 21 | * @param param7 seventh parameter 22 | * @param param8 eight parameter 23 | */ 24 | void invoke(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6, P7 param7, P8 param8); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/TestClosureParams4.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link org.specnaz.utils.TestClosure} for 5 | * parametrized tests taking 4 parameters. 6 | * 7 | * @see #invoke 8 | * @see org.specnaz.utils.TestClosure 9 | * @see ParamsSpecBuilder#should(String, TestClosureParams4) 10 | * @see ParamsSpecBuilder#shouldThrow(Class, String, TestClosureParams4) 11 | */ 12 | @FunctionalInterface 13 | public interface TestClosureParams4 { 14 | /** 15 | * The abstract method of the {@link FunctionalInterface}. 16 | * 17 | * @param param1 the first parameter 18 | * @param param2 the second parameter 19 | * @param param3 the third parameter 20 | * @param param4 the fourth parameter 21 | * @throws Exception can safely throw any Exception 22 | */ 23 | void invoke(P1 param1, P2 param2, P3 param3, P4 param4) throws Exception; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedPositiveTest3.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.impl.TestCaseType; 5 | import org.specnaz.params.TestClosureParams3; 6 | import org.specnaz.utils.TestClosure; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedPositiveTest3 extends 11 | AbstractParametrizedPositiveTest { 12 | private final TestClosureParams3 testBody; 13 | 14 | public ParametrizedPositiveTest3(TestSettings testSettings, 15 | String description, TestClosureParams3 testBody, TestCaseType testCaseType) { 16 | super(testSettings, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure3(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz-testng/resources/specnaz-testng-1.4.pom: -------------------------------------------------------------------------------- 1 | 5 | 4.0.0 6 | 7 | org.specnaz 8 | specnaz-testng 9 | 1.4 10 | 11 | 12 | 13 | org.specnaz 14 | specnaz 15 | 1.4 16 | 17 | 18 | 19 | org.testng 20 | testng 21 | 6.14.3 22 | provided 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/specnaz-testng/src/main/java/org/specnaz/testng/SpecnazMethodInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.testng; 2 | 3 | import org.testng.IMethodInstance; 4 | import org.testng.IMethodInterceptor; 5 | import org.testng.ITestContext; 6 | 7 | import java.util.List; 8 | 9 | public final class SpecnazMethodInterceptor implements IMethodInterceptor { 10 | @Override 11 | public List intercept(List methods, 12 | ITestContext context) { 13 | methods.sort((mi1, mi2) -> { 14 | if (!(mi1.getInstance() instanceof SpecnazTests) || 15 | !(mi2.getInstance() instanceof SpecnazTests)) 16 | return 0; 17 | SpecnazTests st1 = (SpecnazTests) mi1.getInstance(); 18 | SpecnazTests st2 = (SpecnazTests) mi2.getInstance(); 19 | return st1.getSignature().compareTo(st2.getSignature()); 20 | }); 21 | return methods; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedPositiveTest4.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.impl.TestCaseType; 5 | import org.specnaz.params.TestClosureParams4; 6 | import org.specnaz.utils.TestClosure; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedPositiveTest4 extends 11 | AbstractParametrizedPositiveTest { 12 | private final TestClosureParams4 testBody; 13 | 14 | public ParametrizedPositiveTest4(TestSettings testSettings, String description, 15 | TestClosureParams4 testBody, TestCaseType testCaseType) { 16 | super(testSettings, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure4(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedSubgroup6.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.RunnableParams6; 5 | 6 | import java.util.List; 7 | 8 | public class ParametrizedSubgroup6 extends AbstractParametrizedSubgroup { 9 | private final RunnableParams6 specClosure; 10 | 11 | public ParametrizedSubgroup6(String description, 12 | RunnableParams6 specClosure, TestCaseType testCaseType) { 13 | super(description, testCaseType); 14 | this.specClosure = specClosure; 15 | } 16 | 17 | @Override 18 | protected Runnable toSpecClosure(List paramsSet) { 19 | return () -> specClosure.invoke((P1) paramsSet.get(0), (P2) paramsSet.get(1), 20 | (P3) paramsSet.get(2), (P4) paramsSet.get(3), (P5) paramsSet.get(4), (P6) paramsSet.get(5)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin/resources/specnaz-kotlin-1.4.pom: -------------------------------------------------------------------------------- 1 | 5 | 4.0.0 6 | 7 | org.specnaz 8 | specnaz-kotlin 9 | 1.4 10 | 11 | 12 | 13 | org.specnaz 14 | specnaz 15 | 1.4 16 | 17 | 18 | 19 | org.jetbrains.kotlin 20 | kotlin-stdlib 21 | 1.2.0 22 | provided 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/Params3.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * A simple tuple class holding 3 values. 5 | * You use it to provide parameters to the {@link ParamsExpected3} 6 | * and {@link ParamsExpectedException3} classes. 7 | */ 8 | public final class Params3 { 9 | /** 10 | * Factory method. 11 | * 12 | * @param param1 first parameter 13 | * @param param2 second parameter 14 | * @param param3 third parameter 15 | * @return a new instance of the {@link Params3} class 16 | */ 17 | public static Params3 p3(P1 param1, P2 param2, P3 param3) { 18 | return new Params3<>(param1, param2, param3); 19 | } 20 | 21 | public final P1 _1; 22 | public final P2 _2; 23 | public final P3 _3; 24 | 25 | private Params3(P1 param1, P2 param2, P3 param3) { 26 | _1 = param1; 27 | _2 = param2; 28 | _3 = param3; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedPositiveTest5.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.impl.TestCaseType; 5 | import org.specnaz.params.TestClosureParams5; 6 | import org.specnaz.utils.TestClosure; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedPositiveTest5 extends 11 | AbstractParametrizedPositiveTest { 12 | private final TestClosureParams5 testBody; 13 | 14 | public ParametrizedPositiveTest5(TestSettings testSettings, String description, 15 | TestClosureParams5 testBody, TestCaseType testCaseType) { 16 | super(testSettings, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure5(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/impl/TreeNode.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.impl; 2 | 3 | import java.util.Collections; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | import static java.lang.String.format; 8 | 9 | public final class TreeNode { 10 | public final T value; 11 | private TreeNode parent = null; 12 | private final List> children = new LinkedList<>(); 13 | 14 | public TreeNode(T value) { 15 | this.value = value; 16 | } 17 | 18 | public void attach(TreeNode node) { 19 | if (node.parent != null) { 20 | throw new IllegalArgumentException(format("Node %s already has a parent", node)); 21 | } 22 | node.parent = this; 23 | children.add(node); 24 | } 25 | 26 | public TreeNode parent() { 27 | return parent; 28 | } 29 | 30 | public List> children() { 31 | return Collections.unmodifiableList(children); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/TestClosureParams5.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link org.specnaz.utils.TestClosure} for 5 | * parametrized tests taking 5 parameters. 6 | * 7 | * @see #invoke 8 | * @see org.specnaz.utils.TestClosure 9 | * @see ParamsSpecBuilder#should(String, TestClosureParams5) 10 | * @see ParamsSpecBuilder#shouldThrow(Class, String, TestClosureParams5) 11 | */ 12 | public interface TestClosureParams5 { 13 | /** 14 | * The abstract method of the {@link FunctionalInterface}. 15 | * 16 | * @param param1 the first parameter 17 | * @param param2 the second parameter 18 | * @param param3 the third parameter 19 | * @param param4 the fourth parameter 20 | * @param param5 the fifth parameter 21 | * @throws Exception can safely throw any Exception 22 | */ 23 | void invoke(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5) throws Exception; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedPositiveTest6.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.impl.TestCaseType; 5 | import org.specnaz.params.TestClosureParams6; 6 | import org.specnaz.utils.TestClosure; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedPositiveTest6 extends 11 | AbstractParametrizedPositiveTest { 12 | private final TestClosureParams6 testBody; 13 | 14 | public ParametrizedPositiveTest6(TestSettings testSettings, String description, 15 | TestClosureParams6 testBody, TestCaseType testCaseType) { 16 | super(testSettings, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure6(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedExceptionTest1.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.TestClosureParams1; 5 | import org.specnaz.utils.TestClosure; 6 | import org.specnaz.utils.ThrowableExpectations; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedExceptionTest1 extends 11 | AbstractParametrizedExceptionTest { 12 | private final TestClosureParams1

testBody; 13 | 14 | public ParametrizedExceptionTest1(ThrowableExpectations throwableExpectations, 15 | String description, TestClosureParams1

testBody, TestCaseType testCaseType) { 16 | super(throwableExpectations, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure1(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/examples/specnaz-custom-dsl-example/src/main/java/org/specnaz/examples/custom_dsl/given_when_then/SpecnazGivenWhenThen.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.examples.custom_dsl.given_when_then; 2 | 3 | import org.specnaz.core.CoreDslBuilder; 4 | import org.specnaz.core.SpecnazCoreDsl; 5 | 6 | import java.util.function.Consumer; 7 | 8 | public interface SpecnazGivenWhenThen extends SpecnazCoreDsl { 9 | default void given(String description, Consumer closure) { 10 | SpecnazCoreDsl.super.specification("Given " + description, coreDslBuilder -> { 11 | closure.accept(new GivenWhenThenBuilder(coreDslBuilder)); 12 | }); 13 | } 14 | 15 | /** 16 | * Do not call! Use {@link SpecnazGivenWhenThen#given} instead. 17 | */ 18 | @Override 19 | @Deprecated 20 | default void specification(String description, Consumer specClosure) { 21 | throw new UnsupportedOperationException("Use given(description, closure) instead"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedPositiveTest7.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.impl.TestCaseType; 5 | import org.specnaz.params.TestClosureParams7; 6 | import org.specnaz.utils.TestClosure; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedPositiveTest7 extends 11 | AbstractParametrizedPositiveTest { 12 | private final TestClosureParams7 testBody; 13 | 14 | public ParametrizedPositiveTest7(TestSettings testSettings, String description, 15 | TestClosureParams7 testBody, TestCaseType testCaseType) { 16 | super(testSettings, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure7(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedSubgroup7.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.RunnableParams7; 5 | 6 | import java.util.List; 7 | 8 | public final class ParametrizedSubgroup7 extends 9 | AbstractParametrizedSubgroup { 10 | private final RunnableParams7 specClosure; 11 | 12 | public ParametrizedSubgroup7(String description, RunnableParams7 specClosure, 13 | TestCaseType testCaseType) { 14 | super(description, testCaseType); 15 | this.specClosure = specClosure; 16 | } 17 | 18 | @Override 19 | protected Runnable toSpecClosure(List params) { 20 | return () -> specClosure.invoke((P1) params.get(0), (P2) params.get(1), (P3) params.get(2), (P4) params.get(3), 21 | (P5) params.get(4), (P6) params.get(5), (P7) params.get(6)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/specnaz-testng/src/main/java/org/specnaz/testng/impl/SharedAllsFixtures.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.testng.impl; 2 | 3 | import org.specnaz.impl.Executable; 4 | 5 | public final class SharedAllsFixtures { 6 | private final Executable executable; 7 | private final long threshold; 8 | private long executions; 9 | private boolean executed; 10 | private Throwable throwable; 11 | 12 | public SharedAllsFixtures(Executable executable, long threshold) { 13 | this.executable = executable; 14 | this.threshold = threshold; 15 | this.executions = 0; 16 | this.executed = false; 17 | this.throwable = null; 18 | } 19 | 20 | public synchronized Throwable execute() { 21 | if (++executions >= threshold) { 22 | if (!executed) { 23 | executed = true; 24 | throwable = executable.execute(); 25 | } 26 | 27 | return throwable; 28 | } 29 | return null; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/examples/specnaz-kotlin-examples/src/test/kotlin/FocusedKotlinSpec.kt: -------------------------------------------------------------------------------- 1 | import org.assertj.core.api.Assertions.assertThat 2 | import org.assertj.core.api.Assertions.fail 3 | import org.specnaz.kotlin.junit.SpecnazKotlinJUnit 4 | 5 | /** 6 | * This example shows the usage of 'focused' methods in Kotlin, 7 | * and how the fixtures like {@code beginsAll/Each} and 8 | * {@code endsAll/Each} are executed even for groups with all 9 | * tests ignored. 10 | */ 11 | class FocusedKotlinSpec : SpecnazKotlinJUnit("A spec with focused tests", { 12 | var counter = 1 13 | 14 | it.beginsAll { 15 | counter += 1 16 | } 17 | 18 | it.should("ignore a non-focused test") { 19 | fail("this unfocused test should not have been executed") 20 | } 21 | 22 | it.describes("and a subgroup with focused tests") { 23 | @Suppress("DEPRECATION") 24 | it.fshould("execute the parent fixtures for focused tests") { 25 | assertThat(counter).isEqualTo(2) 26 | } 27 | } 28 | }) 29 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/RunnableParams9.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link Runnable} for parametrized 5 | * sub-specifications taking 9 parameters. 6 | * 7 | * @see #invoke 8 | * @see ParamsSpecBuilder#describes(String, RunnableParams9) 9 | */ 10 | @FunctionalInterface 11 | public interface RunnableParams9 { 12 | /** 13 | * The abstract method of the {@link FunctionalInterface}. 14 | * 15 | * @param param1 first parameter 16 | * @param param2 second parameter 17 | * @param param3 third parameter 18 | * @param param4 fourth parameter 19 | * @param param5 fifth parameter 20 | * @param param6 sixth parameter 21 | * @param param7 seventh parameter 22 | * @param param8 eight parameter 23 | * @param param9 ninth parameter 24 | */ 25 | void invoke(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6, P7 param7, P8 param8, P9 param9); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedExceptionTest2.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.TestClosureParams2; 5 | import org.specnaz.utils.TestClosure; 6 | import org.specnaz.utils.ThrowableExpectations; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedExceptionTest2 extends 11 | AbstractParametrizedExceptionTest { 12 | private final TestClosureParams2 testBody; 13 | 14 | public ParametrizedExceptionTest2(ThrowableExpectations throwableExpectations, 15 | String description, TestClosureParams2 testBody, TestCaseType testCaseType) { 16 | super(throwableExpectations, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure2(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedPositiveTest8.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.impl.TestCaseType; 5 | import org.specnaz.params.TestClosureParams8; 6 | import org.specnaz.utils.TestClosure; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedPositiveTest8 extends 11 | AbstractParametrizedPositiveTest { 12 | private final TestClosureParams8 testBody; 13 | 14 | public ParametrizedPositiveTest8(TestSettings testSettings, String description, 15 | TestClosureParams8 testBody, TestCaseType testCaseType) { 16 | super(testSettings, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure8(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedExceptionTest3.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.TestClosureParams3; 5 | import org.specnaz.utils.TestClosure; 6 | import org.specnaz.utils.ThrowableExpectations; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedExceptionTest3 extends 11 | AbstractParametrizedExceptionTest { 12 | private final TestClosureParams3 testBody; 13 | 14 | public ParametrizedExceptionTest3(ThrowableExpectations throwableExpectations, 15 | String description, TestClosureParams3 testBody, TestCaseType testCaseType) { 16 | super(throwableExpectations, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure3(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedPositiveTest9.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.impl.TestCaseType; 5 | import org.specnaz.params.TestClosureParams9; 6 | import org.specnaz.utils.TestClosure; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedPositiveTest9 extends 11 | AbstractParametrizedPositiveTest { 12 | private final TestClosureParams9 testBody; 13 | 14 | public ParametrizedPositiveTest9(TestSettings testSettings, String description, 15 | TestClosureParams9 testBody, TestCaseType testCaseType) { 16 | super(testSettings, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure9(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/examples/specnaz-custom-dsl-example/src/main/java/org/specnaz/examples/custom_dsl/given_when_then/standalone/GivenWhenThenCoreWrapper.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.examples.custom_dsl.given_when_then.standalone; 2 | 3 | import org.specnaz.core.SpecnazCoreDsl; 4 | import org.specnaz.examples.custom_dsl.given_when_then.GivenBuilder; 5 | import org.specnaz.examples.custom_dsl.given_when_then.GivenWhenThenBuilder; 6 | 7 | import java.util.function.Consumer; 8 | 9 | class GivenWhenThenCoreWrapper implements SpecnazCoreDsl { 10 | private final String description; 11 | private final Consumer specClosure; 12 | 13 | public GivenWhenThenCoreWrapper(String description, Consumer specClosure) { 14 | this.description = description; 15 | this.specClosure = specClosure; 16 | } 17 | 18 | public void callSpecification() { 19 | specification(description, coreDslBuilder -> { 20 | specClosure.accept(new GivenWhenThenBuilder(coreDslBuilder)); 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/impl/SingleExceptionTestCase.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.utils.TestClosure; 5 | import org.specnaz.utils.ThrowableExpectations; 6 | 7 | public final class SingleExceptionTestCase extends SingleTestCase { 8 | private final ThrowableExpectations.Wrapper throwableExpectations; 9 | 10 | public SingleExceptionTestCase(ThrowableExpectations throwableExpectations, 11 | String description, TestClosure testBody, TestCaseType type) { 12 | super(new TestSettings(), description, testBody, type); 13 | this.throwableExpectations = new ThrowableExpectations.Wrapper<>(throwableExpectations); 14 | } 15 | 16 | @Override 17 | public Throwable exercise() { 18 | Throwable resultingException = super.exercise(); 19 | return SingleTestCase.invokeCallback(() -> { 20 | throwableExpectations.verify(resultingException); 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedExceptionTest4.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.TestClosureParams4; 5 | import org.specnaz.utils.TestClosure; 6 | import org.specnaz.utils.ThrowableExpectations; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedExceptionTest4 extends 11 | AbstractParametrizedExceptionTest { 12 | private final TestClosureParams4 testBody; 13 | 14 | public ParametrizedExceptionTest4(ThrowableExpectations throwableExpectations, String description, 15 | TestClosureParams4 testBody, TestCaseType testCaseType) { 16 | super(throwableExpectations, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure4(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedSubgroup8.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.RunnableParams8; 5 | 6 | import java.util.List; 7 | 8 | public final class ParametrizedSubgroup8 extends 9 | AbstractParametrizedSubgroup { 10 | private final RunnableParams8 specClosure; 11 | 12 | public ParametrizedSubgroup8(String description, RunnableParams8 specClosure, 13 | TestCaseType testCaseType) { 14 | super(description, testCaseType); 15 | this.specClosure = specClosure; 16 | } 17 | 18 | @Override 19 | protected Runnable toSpecClosure(List params) { 20 | return () -> specClosure.invoke((P1) params.get(0), (P2) params.get(1), (P3) params.get(2), (P4) params.get(3), 21 | (P5) params.get(4), (P6) params.get(5), (P7) params.get(6), (P8) params.get(7)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedExceptionTest5.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.TestClosureParams5; 5 | import org.specnaz.utils.TestClosure; 6 | import org.specnaz.utils.ThrowableExpectations; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedExceptionTest5 extends 11 | AbstractParametrizedExceptionTest { 12 | private final TestClosureParams5 testBody; 13 | 14 | public ParametrizedExceptionTest5(ThrowableExpectations throwableExpectations, String description, 15 | TestClosureParams5 testBody, TestCaseType testCaseType) { 16 | super(throwableExpectations, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure5(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/utils/IntBox.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.utils; 2 | 3 | /** 4 | * A version of the {@link Box} class for primitive {@code int} values. 5 | * For code readability, its constructor is private; 6 | * you create instances using the {@link IntBox#boxWith(int value)} static method. 7 | * 8 | * @see Box 9 | */ 10 | public final class IntBox { 11 | /** 12 | * Creates a new {@link IntBox} wrapping the provided value. 13 | * 14 | * @param value 15 | * the value to wrap in a box 16 | * @return 17 | * a new instance of the {@link IntBox} class with the {@link IntBox#$} field set to {@code value} 18 | */ 19 | public static IntBox boxWith(int value) { 20 | return new IntBox(value); 21 | } 22 | 23 | /** 24 | * The value wrapped in the box. 25 | * It's {@code public} by design, so accessing and modifying it is as concise as possible. 26 | */ 27 | public int $; 28 | 29 | private IntBox(int value) { 30 | this.$ = value; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedExceptionTest6.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.TestClosureParams6; 5 | import org.specnaz.utils.TestClosure; 6 | import org.specnaz.utils.ThrowableExpectations; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedExceptionTest6 extends 11 | AbstractParametrizedExceptionTest { 12 | private final TestClosureParams6 testBody; 13 | 14 | public ParametrizedExceptionTest6(ThrowableExpectations throwableExpectations, String description, 15 | TestClosureParams6 testBody, TestCaseType testCaseType) { 16 | super(throwableExpectations, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure6(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedSubgroup9.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.RunnableParams9; 5 | 6 | import java.util.List; 7 | 8 | public final class ParametrizedSubgroup9 extends 9 | AbstractParametrizedSubgroup { 10 | private final RunnableParams9 specClosure; 11 | 12 | public ParametrizedSubgroup9(String description, RunnableParams9 specClosure, 13 | TestCaseType testCaseType) { 14 | super(description, testCaseType); 15 | this.specClosure = specClosure; 16 | } 17 | 18 | @Override 19 | protected Runnable toSpecClosure(List params) { 20 | return () -> specClosure.invoke((P1) params.get(0), (P2) params.get(1), (P3) params.get(2), (P4) params.get(3), 21 | (P5) params.get(4), (P6) params.get(5), (P7) params.get(6), (P8) params.get(7), (P9) params.get(8)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/utils/ByteBox.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.utils; 2 | 3 | /** 4 | * A version of the {@link Box} class for primitive {@code byte} values. 5 | * For code readability, its constructor is private; 6 | * you create instances using the {@link ByteBox#boxWith(byte value)} static method. 7 | * 8 | * @see Box 9 | */ 10 | public final class ByteBox { 11 | /** 12 | * Creates a new {@link ByteBox} wrapping the provided value. 13 | * 14 | * @param value 15 | * the value to wrap in a box 16 | * @return 17 | * a new instance of the {@link ByteBox} class with the {@link ByteBox#$} field set to {@code value} 18 | */ 19 | public static ByteBox boxWith(byte value) { 20 | return new ByteBox(value); 21 | } 22 | 23 | /** 24 | * The value wrapped in the box. 25 | * It's {@code public} by design, so accessing and modifying it is as concise as possible. 26 | */ 27 | public byte $; 28 | 29 | private ByteBox(byte value) { 30 | this.$ = value; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/utils/CharBox.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.utils; 2 | 3 | /** 4 | * A version of the {@link Box} class for primitive {@code char} values. 5 | * For code readability, its constructor is private; 6 | * you create instances using the {@link CharBox#boxWith(char value)} static method. 7 | * 8 | * @see Box 9 | */ 10 | public final class CharBox { 11 | /** 12 | * Creates a new {@link CharBox} wrapping the provided value. 13 | * 14 | * @param value 15 | * the value to wrap in a box 16 | * @return 17 | * a new instance of the {@link CharBox} class with the {@link CharBox#$} field set to {@code value} 18 | */ 19 | public static CharBox boxWith(char value) { 20 | return new CharBox(value); 21 | } 22 | 23 | /** 24 | * The value wrapped in the box. 25 | * It's {@code public} by design, so accessing and modifying it is as concise as possible. 26 | */ 27 | public char $; 28 | 29 | private CharBox(char value) { 30 | this.$ = value; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/utils/LongBox.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.utils; 2 | 3 | /** 4 | * A version of the {@link Box} class for primitive {@code long} values. 5 | * For code readability, its constructor is private; 6 | * you create instances using the {@link LongBox#boxWith(long value)} static method. 7 | * 8 | * @see Box 9 | */ 10 | public final class LongBox { 11 | /** 12 | * Creates a new {@link LongBox} wrapping the provided value. 13 | * 14 | * @param value 15 | * the value to wrap in a box 16 | * @return 17 | * a new instance of the {@link LongBox} class with the {@link LongBox#$} field set to {@code value} 18 | */ 19 | public static LongBox boxWith(long value) { 20 | return new LongBox(value); 21 | } 22 | 23 | /** 24 | * The value wrapped in the box. 25 | * It's {@code public} by design, so accessing and modifying it is as concise as possible. 26 | */ 27 | public long $; 28 | 29 | private LongBox(long value) { 30 | this.$ = value; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/test/java/spring/Readme.md: -------------------------------------------------------------------------------- 1 | Demonstrates using [Spring JUnit Rules](https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testcontext-junit4-rules) in Specnaz. 2 | 3 | The integration is straightforward, except for one detail: 4 | you need to declare a `public` 'dummy' field, of type 5 | [SpringMethodRule](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/context/junit4/rules/SpringMethodRule.html), 6 | in your Spec class, 7 | and annotate it with the [@Rule](http://junit.org/junit4/javadoc/4.12/org/junit/Rule.html) annotation. 8 | The reason is that Spring's [ClassRule](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/context/junit4/rules/SpringClassRule.html) 9 | has some built-in validation that checks for the presence of that field, 10 | and fails the tests before they even start if it's not found. 11 | The field will not be used at all, and so can be set to `null` safely. 12 | 13 | See [this test](SpringIntegrationSpec.java) for an example. 14 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/TestClosureParams6.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link org.specnaz.utils.TestClosure} for 5 | * parametrized tests taking 6 parameters. 6 | * 7 | * @see #invoke 8 | * @see org.specnaz.utils.TestClosure 9 | * @see ParamsSpecBuilder#should(String, TestClosureParams6) 10 | * @see ParamsSpecBuilder#shouldThrow(Class, String, TestClosureParams6) 11 | */ 12 | @FunctionalInterface 13 | public interface TestClosureParams6 { 14 | /** 15 | * The abstract method of the {@link FunctionalInterface}. 16 | * 17 | * @param param1 the first parameter 18 | * @param param2 the second parameter 19 | * @param param3 the third parameter 20 | * @param param4 the fourth parameter 21 | * @param param5 the fifth parameter 22 | * @param param6 the sixth parameter 23 | * @throws Exception can safely throw any Exception 24 | */ 25 | void invoke(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6) throws Exception; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/AbstractParametrizedExceptionTest.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.SingleExceptionTestCase; 4 | import org.specnaz.impl.SingleTestCase; 5 | import org.specnaz.impl.TestCaseType; 6 | import org.specnaz.utils.ThrowableExpectations; 7 | 8 | import java.util.List; 9 | 10 | public abstract class AbstractParametrizedExceptionTest extends AbstractParametrizedTest { 11 | public final ThrowableExpectations throwableExpectations; 12 | 13 | public AbstractParametrizedExceptionTest(ThrowableExpectations throwableExpectations, 14 | String description, TestCaseType testCaseType) { 15 | super(description, testCaseType); 16 | this.throwableExpectations = throwableExpectations; 17 | } 18 | 19 | @Override 20 | protected SingleTestCase testCase(List params) { 21 | return new SingleExceptionTestCase<>(throwableExpectations, 22 | formatDesc(params), toTestClosure(params), testCaseType); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedExceptionTest7.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.TestClosureParams7; 5 | import org.specnaz.utils.TestClosure; 6 | import org.specnaz.utils.ThrowableExpectations; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedExceptionTest7 extends 11 | AbstractParametrizedExceptionTest { 12 | private final TestClosureParams7 testBody; 13 | 14 | public ParametrizedExceptionTest7(ThrowableExpectations throwableExpectations, String description, 15 | TestClosureParams7 testBody, TestCaseType testCaseType) { 16 | super(throwableExpectations, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure7(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/main/java/dropwizard/HelloWorldConfiguration.java: -------------------------------------------------------------------------------- 1 | package dropwizard; 2 | 3 | import io.dropwizard.Configuration; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import org.hibernate.validator.constraints.NotEmpty; 6 | 7 | /** 8 | * Taken from here. 9 | */ 10 | public class HelloWorldConfiguration extends Configuration { 11 | @NotEmpty 12 | private String template; 13 | 14 | @NotEmpty 15 | private String defaultName = "Stranger"; 16 | 17 | @JsonProperty 18 | public String getTemplate() { 19 | return template; 20 | } 21 | 22 | @JsonProperty 23 | public void setTemplate(String template) { 24 | this.template = template; 25 | } 26 | 27 | @JsonProperty 28 | public String getDefaultName() { 29 | return defaultName; 30 | } 31 | 32 | @JsonProperty 33 | public void setDefaultName(String name) { 34 | this.defaultName = name; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/examples/specnaz-testng-examples/src/test/kotlin/StackKotlinSpec.kt: -------------------------------------------------------------------------------- 1 | import org.specnaz.kotlin.testng.SpecnazKotlinTestNG 2 | import org.testng.Assert 3 | import org.testng.annotations.Test 4 | import java.util.Stack 5 | 6 | /** 7 | * This is the example spec from the Readme file, using Kotlin, 8 | * and running with TestNG as the execution engine. 9 | */ 10 | @Test 11 | class StackKotlinSpec : SpecnazKotlinTestNG("A Stack (Kotlin)", { 12 | var stack = Stack() 13 | 14 | it.endsEach { 15 | stack = Stack() 16 | } 17 | 18 | it.should("be empty when first created") { 19 | Assert.assertTrue(stack.isEmpty()) 20 | } 21 | 22 | it.describes("with 10 and 20 pushed on it") { 23 | it.beginsEach { 24 | stack.push(10) 25 | stack.push(20) 26 | } 27 | 28 | it.should("have size equal to 2") { 29 | Assert.assertEquals(stack.size, 2) 30 | } 31 | 32 | it.should("have 20 as the top element") { 33 | Assert.assertEquals(stack.peek(), 20) 34 | } 35 | } 36 | }) 37 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/utils/FloatBox.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.utils; 2 | 3 | /** 4 | * A version of the {@link Box} class for primitive {@code float} values. 5 | * For code readability, its constructor is private; 6 | * you create instances using the {@link FloatBox#boxWith(float value)} static method. 7 | * 8 | * @see Box 9 | */ 10 | public final class FloatBox { 11 | /** 12 | * Creates a new {@link FloatBox} wrapping the provided value. 13 | * 14 | * @param value 15 | * the value to wrap in a box 16 | * @return 17 | * a new instance of the {@link FloatBox} class with the {@link FloatBox#$} field set to {@code value} 18 | */ 19 | public static FloatBox boxWith(float value) { 20 | return new FloatBox(value); 21 | } 22 | 23 | /** 24 | * The value wrapped in the box. 25 | * It's {@code public} by design, so accessing and modifying it is as concise as possible. 26 | */ 27 | public float $; 28 | 29 | private FloatBox(float value) { 30 | this.$ = value; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/utils/ShortBox.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.utils; 2 | 3 | /** 4 | * A version of the {@link Box} class for primitive {@code short} values. 5 | * For code readability, its constructor is private; 6 | * you create instances using the {@link ShortBox#boxWith(short value)} static method. 7 | * 8 | * @see Box 9 | */ 10 | public final class ShortBox { 11 | /** 12 | * Creates a new {@link ShortBox} wrapping the provided value. 13 | * 14 | * @param value 15 | * the value to wrap in a box 16 | * @return 17 | * a new instance of the {@link ShortBox} class with the {@link ShortBox#$} field set to {@code value} 18 | */ 19 | public static ShortBox boxWith(short value) { 20 | return new ShortBox(value); 21 | } 22 | 23 | /** 24 | * The value wrapped in the box. 25 | * It's {@code public} by design, so accessing and modifying it is as concise as possible. 26 | */ 27 | public short $; 28 | 29 | private ShortBox(short value) { 30 | this.$ = value; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedExceptionTest8.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.TestClosureParams8; 5 | import org.specnaz.utils.TestClosure; 6 | import org.specnaz.utils.ThrowableExpectations; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedExceptionTest8 extends 11 | AbstractParametrizedExceptionTest { 12 | private final TestClosureParams8 testBody; 13 | 14 | public ParametrizedExceptionTest8(ThrowableExpectations throwableExpectations, String description, 15 | TestClosureParams8 testBody, TestCaseType testCaseType) { 16 | super(throwableExpectations, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure8(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/ParametrizedExceptionTest9.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | import org.specnaz.params.TestClosureParams9; 5 | import org.specnaz.utils.TestClosure; 6 | import org.specnaz.utils.ThrowableExpectations; 7 | 8 | import java.util.List; 9 | 10 | public final class ParametrizedExceptionTest9 extends 11 | AbstractParametrizedExceptionTest { 12 | private final TestClosureParams9 testBody; 13 | 14 | public ParametrizedExceptionTest9(ThrowableExpectations throwableExpectations, String description, 15 | TestClosureParams9 testBody, TestCaseType testCaseType) { 16 | super(throwableExpectations, description, testCaseType); 17 | this.testBody = testBody; 18 | } 19 | 20 | @Override 21 | protected TestClosure toTestClosure(List params) { 22 | return Conversions.toTestClosure9(testBody, params); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/utils/DoubleBox.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.utils; 2 | 3 | /** 4 | * A version of the {@link Box} class for primitive {@code double} values. 5 | * For code readability, its constructor is private; 6 | * you create instances using the {@link DoubleBox#boxWith(double value)} static method. 7 | * 8 | * @see Box 9 | */ 10 | public final class DoubleBox { 11 | /** 12 | * Creates a new {@link DoubleBox} wrapping the provided value. 13 | * 14 | * @param value 15 | * the value to wrap in a box 16 | * @return 17 | * a new instance of the {@link DoubleBox} class with the {@link DoubleBox#$} field set to {@code value} 18 | */ 19 | public static DoubleBox boxWith(double value) { 20 | return new DoubleBox(value); 21 | } 22 | 23 | /** 24 | * The value wrapped in the box. 25 | * It's {@code public} by design, so accessing and modifying it is as concise as possible. 26 | */ 27 | public double $; 28 | 29 | private DoubleBox(double value) { 30 | this.$ = value; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/examples/Readme.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | This directory contains various projects demonstrating using Specnaz in different settings. 4 | 5 | * [specnaz-java-examples](specnaz-java-examples) contains examples of using Specnaz with JUnit in Java. 6 | * [specnaz-kotlin-examples](specnaz-kotlin-examples) contains examples of using Specnaz with JUnit in the Kotlin programming language. 7 | * [specnaz-groovy-examples](specnaz-groovy-examples) contains guidance how to use Specnaz in the Groovy programming language. 8 | * [specnaz-junit-rules-examples](specnaz-junit-rules-examples) shows how to leverage the 9 | [JUnit Rules API](https://github.com/junit-team/junit4/wiki/rules) in Specnaz, 10 | including using third-party Rules from [Mockito](http://site.mockito.org/), 11 | [Spring](https://spring.io/) and [Dropwizard](http://www.dropwizard.io). 12 | * [specnaz-testng-examples](specnaz-testng-examples) contains examples of using Specnaz with TestNG in Java and Kotlin. 13 | * [specnaz-custom-dsl-example](specnaz-custom-dsl-example) walks you through extending Specnaz by creating your own custom DSL for defining tests. 14 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/impl/SingleTestCase.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.impl; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.utils.TestClosure; 5 | 6 | public abstract class SingleTestCase { 7 | public static Throwable invokeCallback(TestClosure callback) { 8 | try { 9 | callback.invoke(); 10 | return null; 11 | } catch (AssertionError | Exception e) { 12 | return e; 13 | } 14 | } 15 | 16 | public final TestSettings.Wrapper testSettings; 17 | public final String description; 18 | private final TestClosure testBody; 19 | public final TestCaseType type; 20 | 21 | SingleTestCase(TestSettings testSettings, String description, TestClosure testBody, 22 | TestCaseType testCaseType) { 23 | this.testSettings = new TestSettings.Wrapper(testSettings); 24 | this.description = description; 25 | this.testBody = testBody; 26 | this.type = testCaseType; 27 | } 28 | 29 | public Throwable exercise() { 30 | return invokeCallback(testBody); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/Params4.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * A simple tuple class holding 4 values. 5 | * You use it to provide parameters to the {@link ParamsExpected4} 6 | * and {@link ParamsExpectedException4} classes. 7 | */ 8 | public final class Params4 { 9 | /** 10 | * Factory method. 11 | * 12 | * @param param1 first parameter 13 | * @param param2 second parameter 14 | * @param param3 third parameter 15 | * @param param4 fourth parameter 16 | * @return a new instance of the {@link Params4} class 17 | */ 18 | public static Params4 p4(P1 param1, P2 param2, P3 param3, P4 param4) { 19 | return new Params4<>(param1, param2, param3, param4); 20 | } 21 | 22 | public final P1 _1; 23 | public final P2 _2; 24 | public final P3 _3; 25 | public final P4 _4; 26 | 27 | private Params4(P1 param1, P2 param2, P3 param3, P4 param4) { 28 | _1 = param1; 29 | _2 = param2; 30 | _3 = param3; 31 | _4 = param4; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/examples/specnaz-java-examples/src/test/java/StackSpec.java: -------------------------------------------------------------------------------- 1 | import org.junit.Assert; 2 | import org.specnaz.junit.SpecnazJUnit; 3 | 4 | import java.util.Stack; 5 | 6 | /** 7 | * This is the example spec from the Readme file. 8 | */ 9 | public class StackSpec extends SpecnazJUnit {{ 10 | describes("A Stack", it -> { 11 | Stack stack = new Stack<>(); 12 | 13 | it.endsEach(() -> { 14 | stack.clear(); 15 | }); 16 | 17 | it.should("be empty when first created", () -> { 18 | Assert.assertTrue(stack.isEmpty()); 19 | }); 20 | 21 | it.describes("with 10 and 20 pushed on it", () -> { 22 | it.beginsEach(() -> { 23 | stack.push(10); 24 | stack.push(20); 25 | }); 26 | 27 | it.should("have size equal to 2", () -> { 28 | Assert.assertEquals(2, stack.size()); 29 | }); 30 | 31 | it.should("have 20 as the top element", () -> { 32 | Assert.assertEquals(20, (int)stack.peek()); 33 | }); 34 | }); 35 | }); 36 | }} 37 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/TestClosureParams7.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link org.specnaz.utils.TestClosure} for 5 | * parametrized tests taking 7 parameters. 6 | * 7 | * @see #invoke 8 | * @see org.specnaz.utils.TestClosure 9 | * @see ParamsSpecBuilder#should(String, TestClosureParams7) 10 | * @see ParamsSpecBuilder#shouldThrow(Class, String, TestClosureParams7) 11 | */ 12 | @FunctionalInterface 13 | public interface TestClosureParams7 { 14 | /** 15 | * The abstract method of the {@link FunctionalInterface}. 16 | * 17 | * @param param1 the first parameter 18 | * @param param2 the second parameter 19 | * @param param3 the third parameter 20 | * @param param4 the fourth parameter 21 | * @param param5 the fifth parameter 22 | * @param param6 the sixth parameter 23 | * @param param7 the seventh parameter 24 | * @throws Exception can safely throw any Exception 25 | */ 26 | void invoke(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6, P7 param7) throws Exception; 27 | } 28 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/test/java/built_in_rules/ExpectedExceptionRuleSpec.java: -------------------------------------------------------------------------------- 1 | package built_in_rules; 2 | 3 | import org.junit.rules.ExpectedException; 4 | import org.specnaz.junit.SpecnazJUnit; 5 | import org.specnaz.junit.rules.Rule; 6 | 7 | /** 8 | * An example of using Specnaz with the built-in {@link ExpectedException} Rule. 9 | * 10 | * @see org.specnaz.SpecBuilder#shouldThrow 11 | */ 12 | public class ExpectedExceptionRuleSpec extends SpecnazJUnit { 13 | public Rule expectedException = Rule.of(() -> ExpectedException.none()); 14 | 15 | { 16 | describes("Using the ExpectedException JUnit Rule in Specnaz", it -> { 17 | it.should("correctly set the expected Exception", () -> { 18 | expectedException.r().expect(IllegalArgumentException.class); 19 | 20 | throw new IllegalArgumentException(); 21 | }); 22 | 23 | it.should("correctly re-set the Rule after the first test", () -> { 24 | expectedException.r().reportMissingExceptionWithMessage(""); 25 | }); 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-junit/src/main/kotlin/org/specnaz/kotlin/junit/xSpecnazKotlinJUnit.kt: -------------------------------------------------------------------------------- 1 | package org.specnaz.kotlin.junit 2 | 3 | import org.junit.runner.RunWith 4 | import org.specnaz.kotlin.KotlinSpecBuilder 5 | import org.specnaz.kotlin.SpecnazKotlin 6 | 7 | /** 8 | * A way to ignore all specs in a class that uses [SpecnazKotlinJUnit] as its superclass. 9 | * 10 | * If you want to turn off all specs in a particular class, 11 | * you can't use the [SpecnazKotlin.xdescribes] method if your spec class inherits from 12 | * [SpecnazKotlinJUnit] - the method call is buried in the constructor of the superclass. 13 | * To alleviate that, this class calls [SpecnazKotlin.xdescribes] in its constructor 14 | * instead of [SpecnazKotlin.describes]. Which means all you need to do to ignore all 15 | * specs in a given class is to add an 'x' in front of [SpecnazKotlinJUnit]. 16 | */ 17 | @RunWith(SpecnazKotlinJUnitRunner::class) 18 | abstract class xSpecnazKotlinJUnit(description: String, 19 | specClosure: (KotlinSpecBuilder) -> Unit) : 20 | SpecnazKotlin { 21 | init { 22 | xdescribes(description, specClosure) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/specnaz-junit/src/main/java/org/specnaz/junit/impl/JUnitFrameworkMethod.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.junit.impl; 2 | 3 | import org.junit.runners.model.FrameworkMethod; 4 | import org.specnaz.impl.ExecutableTestCase; 5 | 6 | import java.lang.reflect.Method; 7 | 8 | public final class JUnitFrameworkMethod { 9 | public static FrameworkMethod frameworkMethod(ExecutableTestCase executableTestCase) { 10 | Method method = executableTestCase.testCase.testSettings.method(); 11 | return method == null ? placeholderFrameworkMethod() : frameworkMethod(method); 12 | } 13 | 14 | private static FrameworkMethod placeholderFrameworkMethod() { 15 | Method placeholderMethod; 16 | try { 17 | placeholderMethod = JUnitFrameworkMethod.class.getMethod("placeholderMethod"); 18 | } catch (NoSuchMethodException e) { 19 | throw new RuntimeException(e); 20 | } 21 | return frameworkMethod(placeholderMethod); 22 | } 23 | 24 | private static FrameworkMethod frameworkMethod(Method method) { 25 | return new FrameworkMethod(method); 26 | } 27 | 28 | public void placeholderMethod() { 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/TestClosureParams8.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link org.specnaz.utils.TestClosure} for 5 | * parametrized tests taking 8 parameters. 6 | * 7 | * @see #invoke 8 | * @see org.specnaz.utils.TestClosure 9 | * @see ParamsSpecBuilder#should(String, TestClosureParams8) 10 | * @see ParamsSpecBuilder#shouldThrow(Class, String, TestClosureParams8) 11 | */ 12 | @FunctionalInterface 13 | public interface TestClosureParams8 { 14 | /** 15 | * The abstract method of the {@link FunctionalInterface}. 16 | * 17 | * @param param1 the first parameter 18 | * @param param2 the second parameter 19 | * @param param3 the third parameter 20 | * @param param4 the fourth parameter 21 | * @param param5 the fifth parameter 22 | * @param param6 the sixth parameter 23 | * @param param7 the seventh parameter 24 | * @param param8 the eight parameter 25 | * @throws Exception can safely throw any Exception 26 | */ 27 | void invoke(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6, P7 param7, P8 param8) throws Exception; 28 | } 29 | -------------------------------------------------------------------------------- /src/examples/specnaz-testng-examples/src/test/java/StackSpec.java: -------------------------------------------------------------------------------- 1 | import org.specnaz.testng.SpecnazFactoryTestNG; 2 | import org.testng.Assert; 3 | import org.testng.annotations.Test; 4 | 5 | import java.util.Stack; 6 | 7 | /** 8 | * This is the example spec from the Readme file, 9 | * running using TestNG as the execution engine. 10 | */ 11 | @Test 12 | public class StackSpec implements SpecnazFactoryTestNG {{ 13 | describes("A Stack", it -> { 14 | Stack stack = new Stack<>(); 15 | 16 | it.endsEach(() -> { 17 | stack.clear(); 18 | }); 19 | 20 | it.should("be empty when first created", () -> { 21 | Assert.assertTrue(stack.isEmpty()); 22 | }); 23 | 24 | it.describes("with 10 and 20 pushed on it", () -> { 25 | it.beginsEach(() -> { 26 | stack.push(10); 27 | stack.push(20); 28 | }); 29 | 30 | it.should("have size equal to 2", () -> { 31 | Assert.assertEquals(stack.size(), 2); 32 | }); 33 | 34 | it.should("have 20 as the top element", () -> { 35 | Assert.assertEquals((int) stack.peek(), 20); 36 | }); 37 | }); 38 | }); 39 | }} 40 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/Params5.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * A simple tuple class holding 5 values. 5 | * You use it to provide parameters to the {@link ParamsExpected5} 6 | * and {@link ParamsExpectedException5} classes. 7 | */ 8 | public final class Params5 { 9 | /** 10 | * Factory method. 11 | * 12 | * @param param1 first parameter 13 | * @param param2 second parameter 14 | * @param param3 third parameter 15 | * @param param4 fourth parameter 16 | * @param param5 fifth parameter 17 | * @return a new instance of the {@link Params5} class 18 | */ 19 | public static Params5 p5(P1 param1, P2 param2, P3 param3, P4 param4, 20 | P5 param5) { 21 | return new Params5<>(param1, param2, param3, param4, param5); 22 | } 23 | 24 | public final P1 _1; 25 | public final P2 _2; 26 | public final P3 _3; 27 | public final P4 _4; 28 | public final P5 _5; 29 | 30 | private Params5(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5) { 31 | _1 = param1; 32 | _2 = param2; 33 | _3 = param3; 34 | _4 = param4; 35 | _5 = param5; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/TestClosureParams9.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * The equivalent of {@link org.specnaz.utils.TestClosure} for 5 | * parametrized tests taking 9 parameters. 6 | * 7 | * @see #invoke 8 | * @see org.specnaz.utils.TestClosure 9 | * @see ParamsSpecBuilder#should(String, TestClosureParams9) 10 | * @see ParamsSpecBuilder#shouldThrow(Class, String, TestClosureParams9) 11 | */ 12 | @FunctionalInterface 13 | public interface TestClosureParams9 { 14 | /** 15 | * The abstract method of the {@link FunctionalInterface}. 16 | * 17 | * @param param1 the first parameter 18 | * @param param2 the second parameter 19 | * @param param3 the third parameter 20 | * @param param4 the fourth parameter 21 | * @param param5 the fifth parameter 22 | * @param param6 the sixth parameter 23 | * @param param7 the seventh parameter 24 | * @param param8 the eight parameter 25 | * @param param9 the ninth parameter 26 | * @throws Exception can safely throw any Exception 27 | */ 28 | void invoke(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6, P7 param7, P8 param8, P9 param9) 29 | throws Exception; 30 | } 31 | -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | Version 1.4 (2018-07-29) 2 | ------------------------ 3 | - added TestNG support 4 | 5 | Version 1.3.1 (2018-05-06) 6 | -------------------------- 7 | - corrected a bug where Specnaz worked only with JUnit version 4.12 8 | - corrected a bug where test method annotations were not being passed correctly to JUnit Test Rules 9 | 10 | Version 1.3 (2018-02-27) 11 | ------------------------ 12 | - added support for JUnit Rules ([Issue #1](https://github.com/skinny85/specnaz/issues/1)) 13 | - added support for writing parametrized tests 14 | 15 | Version 1.2 (2017-12-25) 16 | ------------------------ 17 | - added the capability to focus tests with `fshould`, `fshouldThrow` and `fdescribes` 18 | - added the capability to ignore tests with `xshould`, `xshouldThrow` and `xdescribes` 19 | - changed `shouldThrow` to allow specifying further assertions on the thrown Exception 20 | ([Pull Request #4](https://github.com/skinny85/specnaz/pull/4)) 21 | 22 | Version 1.1 (2017-07-26) 23 | ------------------------ 24 | - added `shouldThrow` for Java and Kotlin - [Issue #2](https://github.com/skinny85/specnaz/issues/2) 25 | 26 | Version 1.0 (2016-09-09) 27 | ------------------------ 28 | - first public release 29 | - `should`, `beginsAll/Each`, `endsAll/Each`, `describes` 30 | - Kotlin support 31 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/main/java/dropwizard/HelloWorldApplication.java: -------------------------------------------------------------------------------- 1 | package dropwizard; 2 | 3 | import dropwizard.resources.HelloWorldResource; 4 | import io.dropwizard.Application; 5 | import io.dropwizard.setup.Bootstrap; 6 | import io.dropwizard.setup.Environment; 7 | 8 | /** 9 | * Taken from here. 10 | */ 11 | public class HelloWorldApplication extends Application { 12 | public static void main(String[] args) throws Exception { 13 | new HelloWorldApplication().run(args); 14 | } 15 | 16 | @Override 17 | public String getName() { 18 | return "hello-world"; 19 | } 20 | 21 | @Override 22 | public void initialize(Bootstrap bootstrap) { 23 | // nothing to do yet 24 | } 25 | 26 | @Override 27 | public void run(HelloWorldConfiguration configuration, 28 | Environment environment) { 29 | final HelloWorldResource resource = new HelloWorldResource( 30 | configuration.getTemplate(), 31 | configuration.getDefaultName() 32 | ); 33 | environment.jersey().register(resource); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/examples/specnaz-kotlin-examples/src/test/kotlin/KotlinParametrizedSpec.kt: -------------------------------------------------------------------------------- 1 | import org.assertj.core.api.Assertions.assertThat 2 | import org.specnaz.kotlin.params.junit.SpecnazKotlinParamsJUnit 3 | import org.specnaz.params.Params2.p2 4 | import org.specnaz.params.Params3.p3 5 | 6 | /** 7 | * Example of a parametrized Kotlin spec. 8 | */ 9 | class KotlinParametrizedSpec : SpecnazKotlinParamsJUnit("A parametrized spec", { 10 | it.should("confirm that %1 + %2 = %3") { a: Int, b: Int, c: Int -> 11 | assertThat(a + b).isEqualTo(c) 12 | }.provided(listOf( 13 | p3(1, 2, 3), 14 | p3(4, 4, 8), 15 | p3(-3, 3, 0), 16 | p3(Int.MAX_VALUE, 1, Int.MIN_VALUE) 17 | )) 18 | 19 | it.shouldThrow("when parsing '%1' as an Int") { str -> 20 | Integer.parseInt(str) 21 | }.provided("cafe", "BABE").withoutCause() 22 | 23 | it.describes("with '%1' as the argument") { str: String, result: Int -> 24 | it.should("correctly parse '$str' as an Int = $result in radix %1") { radix -> 25 | assertThat(Integer.parseInt(str, radix)).isEqualTo(result) 26 | }.provided(16) 27 | }.provided( 28 | p2("cafe", 51966), 29 | p2("BABE", 47806) 30 | ) 31 | }) 32 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-testng/src/main/kotlin/org/specnaz/kotlin/params/testng/SpecnazKotlinParamsFactoryTestNG.kt: -------------------------------------------------------------------------------- 1 | package org.specnaz.kotlin.params.testng 2 | 3 | import org.specnaz.impl.SpecsRegistryViolation 4 | import org.specnaz.kotlin.params.SpecnazKotlinParams 5 | import org.specnaz.testng.impl.SpecnazTestNgSpecFactory 6 | import org.testng.annotations.Factory 7 | 8 | /** 9 | * The parametrized equivalent of [org.specnaz.kotlin.testng.SpecnazKotlinFactoryTestNG]. 10 | * You use it exactly like [org.specnaz.kotlin.testng.SpecnazKotlinFactoryTestNG]. 11 | * 12 | * @see org.specnaz.kotlin.testng.SpecnazKotlinFactoryTestNG 13 | * @see org.specnaz.kotlin.params.SpecnazKotlinParams 14 | * @see SpecnazKotlinParamsTestNG 15 | */ 16 | interface SpecnazKotlinParamsFactoryTestNG : SpecnazKotlinParams { 17 | /** 18 | * The parametrized equivalent of [org.specnaz.kotlin.testng.SpecnazKotlinTestNG.specs]. 19 | */ 20 | @Factory 21 | fun specs(): Array { 22 | try { 23 | return SpecnazTestNgSpecFactory.specs(this) 24 | } catch (e: SpecsRegistryViolation) { 25 | throw IllegalStateException("SpecnazKotlinParams.describes() was never called in the " + 26 | "no-argument constructor of " + this.javaClass.simpleName) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/main/java/dropwizard/resources/HelloWorldResource.java: -------------------------------------------------------------------------------- 1 | package dropwizard.resources; 2 | 3 | import com.codahale.metrics.annotation.Timed; 4 | import dropwizard.api.Saying; 5 | 6 | import javax.ws.rs.GET; 7 | import javax.ws.rs.Path; 8 | import javax.ws.rs.Produces; 9 | import javax.ws.rs.QueryParam; 10 | import javax.ws.rs.core.MediaType; 11 | import java.util.Optional; 12 | import java.util.concurrent.atomic.AtomicLong; 13 | 14 | /** 15 | * Taken from here. 16 | */ 17 | @Path("/hello-world") 18 | @Produces(MediaType.APPLICATION_JSON) 19 | public class HelloWorldResource { 20 | private final String template; 21 | private final String defaultName; 22 | private final AtomicLong counter; 23 | 24 | public HelloWorldResource(String template, String defaultName) { 25 | this.template = template; 26 | this.defaultName = defaultName; 27 | this.counter = new AtomicLong(); 28 | } 29 | 30 | @GET 31 | @Timed 32 | public Saying sayHello(@QueryParam("name") Optional name) { 33 | final String value = String.format(template, name.orElse(defaultName)); 34 | return new Saying(counter.incrementAndGet(), value); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-testng/src/main/kotlin/org/specnaz/kotlin/testng/xSpecnazKotlinTestNG.kt: -------------------------------------------------------------------------------- 1 | package org.specnaz.kotlin.testng 2 | 3 | import org.specnaz.kotlin.KotlinSpecBuilder 4 | import org.testng.annotations.Test 5 | 6 | /** 7 | * A way to ignore all specs in a class that uses [SpecnazKotlinTestNG] as its superclass. 8 | * 9 | * If you want to turn off all specs in a particular class, 10 | * you can't use the [org.specnaz.kotlin.SpecnazKotlin.xdescribes] 11 | * method if your spec class inherits from [SpecnazKotlinTestNG] - 12 | * the method call to [org.specnaz.kotlin.SpecnazKotlin.describes] 13 | * is buried in the constructor of [SpecnazKotlinTestNG]. 14 | * To alleviate that, this class calls [org.specnaz.kotlin.SpecnazKotlin.xdescribes] 15 | * in its constructor instead of [org.specnaz.kotlin.SpecnazKotlin.describes]. 16 | * Which means all you need to do to ignore all 17 | * specs in a given class extending [SpecnazKotlinTestNG] 18 | * is add an 'x' in front of [SpecnazKotlinTestNG]. 19 | * 20 | * @see SpecnazKotlinTestNG 21 | * @see org.specnaz.kotlin.SpecnazKotlin.xdescribes 22 | */ 23 | @Test 24 | abstract class xSpecnazKotlinTestNG(description: String, 25 | specClosure: (KotlinSpecBuilder) -> Unit) : SpecnazKotlinFactoryTestNG { 26 | init { 27 | xdescribes(description, specClosure) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/examples/specnaz-custom-dsl-example/src/main/java/org/specnaz/examples/custom_dsl/given_when_then/GivenWhenThenBuilder.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.examples.custom_dsl.given_when_then; 2 | 3 | import org.specnaz.core.CoreDslBuilder; 4 | import org.specnaz.utils.TestClosure; 5 | 6 | import java.util.function.Consumer; 7 | 8 | public class GivenWhenThenBuilder implements GivenBuilder, ThensBuilder { 9 | private final CoreDslBuilder coreDslBuilder; 10 | 11 | public GivenWhenThenBuilder(CoreDslBuilder coreDslBuilder) { 12 | this.coreDslBuilder = coreDslBuilder; 13 | } 14 | 15 | @Override 16 | public void given(String description, TestClosure action, Runnable closure) { 17 | coreDslBuilder.subSpecification(description, () -> { 18 | coreDslBuilder.beforeAll(action); 19 | 20 | closure.run(); 21 | }); 22 | } 23 | 24 | @Override 25 | public void when(String description, TestClosure action, Consumer thens) { 26 | coreDslBuilder.subSpecification("when " + description, () -> { 27 | coreDslBuilder.beforeAll(action); 28 | 29 | thens.accept(this); 30 | }); 31 | } 32 | 33 | @Override 34 | public void then(String description, TestClosure testBody) { 35 | coreDslBuilder.test("then " + description, testBody); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/examples/specnaz-custom-dsl-example/src/main/java/org/specnaz/examples/custom_dsl/given_when_then/standalone/GivenWhenThenRegistry.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.examples.custom_dsl.given_when_then.standalone; 2 | 3 | import org.specnaz.examples.custom_dsl.given_when_then.GivenBuilder; 4 | 5 | import java.util.IdentityHashMap; 6 | import java.util.function.Consumer; 7 | 8 | public class GivenWhenThenRegistry { 9 | private static final IdentityHashMap STORE = new IdentityHashMap<>(); 10 | 11 | public static void add(SpecnazGivenWhenThenStandalone specInstance, String description, Consumer specClosure) 12 | throws IllegalArgumentException { 13 | GivenWhenThenCoreWrapper prev = STORE.putIfAbsent(specInstance, 14 | new GivenWhenThenCoreWrapper(description, specClosure)); 15 | if (prev != null) 16 | throw new IllegalArgumentException("Instance '" + specInstance + "' already registered"); 17 | } 18 | 19 | static GivenWhenThenCoreWrapper get(SpecnazGivenWhenThenStandalone specInstance) throws IllegalArgumentException { 20 | GivenWhenThenCoreWrapper ret = STORE.get(specInstance); 21 | if (ret == null) 22 | throw new IllegalArgumentException("Instance '" + specInstance + "' was never registered"); 23 | return ret; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/Params6.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * A simple tuple class holding 6 values. 5 | * You use it to provide parameters to the {@link ParamsExpected6} 6 | * and {@link ParamsExpectedException6} classes. 7 | */ 8 | public final class Params6 { 9 | /** 10 | * Factory method. 11 | * 12 | * @param param1 first parameter 13 | * @param param2 second parameter 14 | * @param param3 third parameter 15 | * @param param4 fourth parameter 16 | * @param param5 fifth parameter 17 | * @param param6 sixth parameter 18 | * @return a new instance of the {@link Params6} class 19 | */ 20 | public static Params6 p6(P1 param1, P2 param2, P3 param3, P4 param4, 21 | P5 param5, P6 param6) { 22 | return new Params6<>(param1, param2, param3, param4, param5, param6); 23 | } 24 | 25 | public final P1 _1; 26 | public final P2 _2; 27 | public final P3 _3; 28 | public final P4 _4; 29 | public final P5 _5; 30 | public final P6 _6; 31 | 32 | private Params6(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6) { 33 | _1 = param1; 34 | _2 = param2; 35 | _3 = param3; 36 | _4 = param4; 37 | _5 = param5; 38 | _6 = param6; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/Readme.md: -------------------------------------------------------------------------------- 1 | Specnaz support for JUnit Rules 2 | ------------------------------- 3 | 4 | This sub-project shows examples of tests leveraging Specnaz's support for the 5 | [JUnit Rules API](https://github.com/junit-team/junit4/wiki/rules). 6 | The project contains different packages, demonstrating using various pre-existing Rules: 7 | 8 | * [built_in_rules](src/test/java/built_in_rules) shows examples of using Rules that are distributed with JUnit, 9 | like [ExpectedException](http://junit.org/junit4/javadoc/4.12/org/junit/rules/ExpectedException.html) 10 | and [TestName](http://junit.org/junit4/javadoc/4.12/org/junit/rules/TestName.html) 11 | * [mockito](src/test/java/mockito) shows how to use 12 | [Mockito's JUnit Rule](https://static.javadoc.io/org.mockito/mockito-core/1.10.19/org/mockito/junit/MockitoRule.html) 13 | in Specnaz 14 | * [spring](src/test/java/spring) shows how to use the 15 | [Spring JUnit Rules](https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testcontext-junit4-rules) 16 | in Specnaz 17 | * [dropwizard](src/test/java/dropwizard) shows how to use 18 | [Dropwizard's ResourceTestRule](http://www.dropwizard.io/1.2.2/docs/manual/testing.html#testing-resources) 19 | in Specnaz 20 | 21 | Check out the [main documentation on JUnit Rules](../../../docs/reference-manual.md#junit-rules) 22 | for more details on how to use JUnit Rules in Specnaz. 23 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/test/java/mockito/MockAnnotationMockitoRuleSpec.java: -------------------------------------------------------------------------------- 1 | package mockito; 2 | 3 | import org.mockito.Mock; 4 | import org.mockito.junit.MockitoJUnit; 5 | import org.mockito.junit.MockitoRule; 6 | import org.specnaz.junit.SpecnazJUnit; 7 | import org.specnaz.junit.rules.Rule; 8 | 9 | import java.util.List; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | import static org.mockito.Mockito.when; 13 | 14 | /** 15 | * A test showing how to use the {@link MockitoRule} to populate fields 16 | * annotated with {@link Mock}. 17 | */ 18 | public class MockAnnotationMockitoRuleSpec extends SpecnazJUnit { 19 | // Mockito Rules are not meant to be used 20 | @SuppressWarnings("unused") 21 | public Rule mockitoRule = Rule.of(() -> MockitoJUnit.rule()); 22 | 23 | @Mock 24 | List listMock; 25 | 26 | { 27 | describes("Using the JUnit Mockito Rule in Specnaz", it -> { 28 | it.should("initialize fields annotated with @Mock", () -> { 29 | assertThat(listMock).isNotNull(); 30 | 31 | when(listMock.get(0)).thenReturn(400 + 56); 32 | 33 | assertThat(listMock.get(0)).isEqualTo(456); 34 | }); 35 | 36 | it.should("reset the mocks after every test", () -> { 37 | assertThat(listMock.get(0)).isNull(); 38 | }); 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/impl/SpecParser.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.impl; 2 | 3 | import java.util.Collection; 4 | 5 | public final class SpecParser { 6 | private final SpecDescriptor specDescriptor; 7 | private TreeNode rootTestsGroupNode; 8 | 9 | public SpecParser(Object specInstance) throws SpecsRegistryViolation { 10 | this.specDescriptor = SpecsRegistry.specFor(specInstance); 11 | } 12 | 13 | public String name() { 14 | return specDescriptor.description; 15 | } 16 | 17 | public TreeNode testsPlan() { 18 | if (rootTestsGroupNode == null) 19 | rootTestsGroupNode = formulateTestPlan(); 20 | return rootTestsGroupNode; 21 | } 22 | 23 | public Collection testsGroupNodeExecutors() { 24 | TreeNode testsPlan = testsPlan(); 25 | return new TestsGroupNodeExecutor(testsPlan, testsPlan.value.containsFocusedTests) 26 | .testsGroupNodeExecutors(); 27 | } 28 | 29 | private TreeNode formulateTestPlan() { 30 | TestsTreeCoreDslBuilder testsTreeCoreDslBuilder = new TestsTreeCoreDslBuilder(name(), specDescriptor.ignoredTestGroup 31 | ? TestCaseType.IGNORED 32 | : TestCaseType.REGULAR); 33 | specDescriptor.specClosure.accept(testsTreeCoreDslBuilder); 34 | return testsTreeCoreDslBuilder.spec(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-junit/src/main/kotlin/org/specnaz/kotlin/junit/SpecnazKotlinJUnit.kt: -------------------------------------------------------------------------------- 1 | package org.specnaz.kotlin.junit 2 | 3 | import org.junit.runner.RunWith 4 | import org.specnaz.junit.SpecnazJUnit 5 | import org.specnaz.kotlin.KotlinSpecBuilder 6 | import org.specnaz.kotlin.SpecnazKotlin 7 | 8 | /** 9 | * The equivalent of [SpecnazJUnit] for Kotlin. 10 | * 11 | * Implements [SpecnazKotlin] and declares [SpecnazKotlinJUnitRunner] as the JUnit 12 | * runner with the [RunWith] annotation. 13 | * 14 | * Useful when your test class does not need to extend any particular class. 15 | * Because it calls [SpecnazKotlin.describes] in its primary constructor, 16 | * it allows you to save some code and one level of indentation 17 | * compared to implementing [SpecnazKotlin] directly: 18 | * 19 | * ```kotlin 20 | * @RunWith(SpecnazKotlinJUnitRunner::class) 21 | * class SomeSpec : SpecnazKotlin { init { 22 | * describes("my spec") { 23 | * // spec body here... 24 | * } 25 | * } 26 | * ``` 27 | * 28 | * versus: 29 | * 30 | * ```kotlin 31 | * class SomeSpec : SpecnazKotlinJunit("my spec", { 32 | * // spec body here... 33 | * }) 34 | * ``` 35 | */ 36 | @RunWith(SpecnazKotlinJUnitRunner::class) 37 | abstract class SpecnazKotlinJUnit(description: String, 38 | specClosure: (KotlinSpecBuilder) -> Unit) : 39 | SpecnazKotlin { 40 | init { 41 | describes(description, specClosure) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/impl/SpecsRegistry.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.impl; 2 | 3 | import org.specnaz.core.CoreDslBuilder; 4 | 5 | import java.util.IdentityHashMap; 6 | import java.util.function.Consumer; 7 | 8 | import static java.lang.String.format; 9 | 10 | public final class SpecsRegistry { 11 | private static final IdentityHashMap REGISTRY = 12 | new IdentityHashMap<>(); 13 | 14 | public static void register(Object specInstance, String description, 15 | boolean ignoredTestGroup, 16 | Consumer specClosure) throws SpecsRegistryViolation { 17 | SpecDescriptor prev = REGISTRY.putIfAbsent(specInstance, 18 | new SpecDescriptor(description, ignoredTestGroup, specClosure)); 19 | if (prev != null) 20 | throw new SpecsRegistryViolation( 21 | "Test object '%s' already registered", specInstance); 22 | } 23 | 24 | static SpecDescriptor specFor(Object specInstance) throws SpecsRegistryViolation { 25 | SpecDescriptor ret = REGISTRY.get(specInstance); 26 | if (ret == null) 27 | throw new SpecsRegistryViolation( 28 | "Test object '%s' was never registered", specInstance); 29 | return ret; 30 | } 31 | 32 | SpecsRegistry() { 33 | throw new UnsupportedOperationException("Cannot create instances of SpecsRegistry"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-testng/src/main/kotlin/org/specnaz/kotlin/testng/SpecnazKotlinAlterSuiteListener.kt: -------------------------------------------------------------------------------- 1 | package org.specnaz.kotlin.testng 2 | 3 | import org.specnaz.kotlin.SpecnazKotlin 4 | import org.specnaz.kotlin.params.SpecnazKotlinParams 5 | import org.testng.IAlterSuiteListener 6 | import org.testng.xml.XmlClass 7 | import org.testng.xml.XmlSuite 8 | import org.testng.xml.XmlTest 9 | 10 | class SpecnazKotlinAlterSuiteListener : IAlterSuiteListener { 11 | override fun alter(xmlSuites: List) { 12 | for (xmlSuite in xmlSuites) { 13 | alterXmlSuite(xmlSuite) 14 | } 15 | } 16 | 17 | private fun alterXmlSuite(xmlSuite: XmlSuite) { 18 | xmlSuite.tests = xmlSuite.tests 19 | .map { xmlTest -> alterXmlTest(xmlTest) } 20 | } 21 | 22 | private fun alterXmlTest(xmlTest: XmlTest): XmlTest { 23 | xmlTest.classes = xmlTest.classes 24 | .map { xmlClass -> alterXmlClass(xmlClass) } 25 | return xmlTest 26 | } 27 | 28 | private fun alterXmlClass(xmlClass: XmlClass): XmlClass { 29 | if (isSpecnazKotlinClass(xmlClass)) 30 | xmlClass.excludedMethods.add(".*describes") 31 | return xmlClass 32 | } 33 | 34 | private fun isSpecnazKotlinClass(xmlClass: XmlClass): Boolean { 35 | return SpecnazKotlin::class.java.isAssignableFrom(xmlClass.supportClass) || 36 | SpecnazKotlinParams::class.java.isAssignableFrom(xmlClass.supportClass) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/Params7.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * A simple tuple class holding 7 values. 5 | * You use it to provide parameters to the {@link ParamsExpected7} 6 | * and {@link ParamsExpectedException7} classes. 7 | */ 8 | public final class Params7 { 9 | /** 10 | * Factory method. 11 | * 12 | * @param param1 first parameter 13 | * @param param2 second parameter 14 | * @param param3 third parameter 15 | * @param param4 fourth parameter 16 | * @param param5 fifth parameter 17 | * @param param6 sixth parameter 18 | * @param param7 seventh parameter 19 | * @return a new instance of the {@link Params7} class 20 | */ 21 | public static Params7 p7(P1 param1, P2 param2, P3 param3, P4 param4, 22 | P5 param5, P6 param6, P7 param7) { 23 | return new Params7<>(param1, param2, param3, param4, param5, param6, param7); 24 | } 25 | 26 | public final P1 _1; 27 | public final P2 _2; 28 | public final P3 _3; 29 | public final P4 _4; 30 | public final P5 _5; 31 | public final P6 _6; 32 | public final P7 _7; 33 | 34 | private Params7(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6, P7 param7) { 35 | _1 = param1; 36 | _2 = param2; 37 | _3 = param3; 38 | _4 = param4; 39 | _5 = param5; 40 | _6 = param6; 41 | _7 = param7; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/examples/specnaz-junit-rules-examples/src/test/java/dropwizard/HelloWorldIntegrationSpec.java: -------------------------------------------------------------------------------- 1 | package dropwizard; 2 | 3 | import dropwizard.api.Saying; 4 | import io.dropwizard.testing.ResourceHelpers; 5 | import io.dropwizard.testing.junit.DropwizardAppRule; 6 | import org.glassfish.jersey.client.JerseyClientBuilder; 7 | import org.specnaz.junit.SpecnazJUnit; 8 | import org.specnaz.junit.rules.Rule; 9 | 10 | import javax.ws.rs.client.Client; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | /** 15 | * Taken from here. 16 | */ 17 | public class HelloWorldIntegrationSpec extends SpecnazJUnit { 18 | public Rule> appRule = Rule.of(() -> 19 | new DropwizardAppRule<>(HelloWorldApplication.class, 20 | ResourceHelpers.resourceFilePath("hello-world.yml"))); 21 | 22 | { 23 | describes("The Dropwizard HelloWorld application", it -> { 24 | it.should("greet 'dropwizard' correctly", () -> { 25 | Client client = new JerseyClientBuilder().build(); 26 | Saying result = client.target( 27 | String.format("http://localhost:%d/hello-world", appRule.r().getLocalPort()) 28 | ).queryParam("name", "dropwizard").request().get(Saying.class); 29 | 30 | assertThat(result.getContent()).isEqualTo("Hello, dropwizard!"); 31 | }); 32 | }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-testng/src/main/kotlin/org/specnaz/kotlin/testng/SpecnazKotlinTestNG.kt: -------------------------------------------------------------------------------- 1 | package org.specnaz.kotlin.testng 2 | 3 | import org.specnaz.kotlin.KotlinSpecBuilder 4 | import org.testng.annotations.Test 5 | 6 | /** 7 | * Helper class for Specnaz specs in Kotlin using TestNG. 8 | * 9 | * This class is the TestNG equivalent of the 10 | * [org.specnaz.kotlin.junit.SpecnazKotlinJUnit] class. 11 | * It implements the [SpecnazKotlinFactoryTestNG] interface and calls the 12 | * [org.specnaz.kotlin.SpecnazKotlin.describes] in its constructor. 13 | * 14 | * It's useful if your test class does not need to extend any particular class. 15 | * In that case, you can extend this class, annotate it with [Test], 16 | * and pass your description and specification-building closure directly in the constructor, 17 | * thus saving some boilerplate (and one level of indentation). 18 | * 19 | * Example: 20 | * 21 | * ```kotlin 22 | * import org.specnaz.kotlin.testng.SpecnazKotlinTestNG 23 | * import org.testng.annotations.Test 24 | * 25 | * @Test 26 | * class MySpec : SpecnazKotlinTestNG("My specification", { 27 | * // use 'it' here to construct the specification... 28 | * }) 29 | * ``` 30 | * 31 | * @see SpecnazKotlinFactoryTestNG 32 | * @see xSpecnazKotlinTestNG 33 | * @see org.specnaz.kotlin.SpecnazKotlin 34 | */ 35 | @Test 36 | abstract class SpecnazKotlinTestNG(description: String, 37 | specClosure: (KotlinSpecBuilder) -> Unit) : SpecnazKotlinFactoryTestNG { 38 | init { 39 | describes(description, specClosure) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/specnaz-junit/src/main/java/org/specnaz/junit/impl/TestCases2DescriptionsMap.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.junit.impl; 2 | 3 | import org.junit.runner.Description; 4 | import org.specnaz.impl.SingleTestCase; 5 | 6 | import java.util.IdentityHashMap; 7 | 8 | public final class TestCases2DescriptionsMap { 9 | public static final class Builder { 10 | private final IdentityHashMap testCases = new IdentityHashMap<>(), 11 | teardowns = new IdentityHashMap<>(); 12 | 13 | public void addDescMapping(SingleTestCase testCase, Description description) { 14 | testCases.put(testCase, description); 15 | } 16 | 17 | public void addTeardownMapping(SingleTestCase testCase, Description description) { 18 | teardowns.put(testCase, description); 19 | } 20 | 21 | public TestCases2DescriptionsMap build() { 22 | return new TestCases2DescriptionsMap(testCases, teardowns); 23 | } 24 | } 25 | 26 | private final IdentityHashMap testCases, teardowns; 27 | 28 | private TestCases2DescriptionsMap(IdentityHashMap testCases, 29 | IdentityHashMap teardowns) { 30 | this.testCases = testCases; 31 | this.teardowns = teardowns; 32 | } 33 | 34 | public Description findDesc(SingleTestCase testCase) { 35 | return testCases.get(testCase); 36 | } 37 | 38 | public Description findTeardown(SingleTestCase testCase) { 39 | return teardowns.get(testCase); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-junit/resources/specnaz-kotlin-junit-1.4.pom: -------------------------------------------------------------------------------- 1 | 5 | 4.0.0 6 | 7 | org.specnaz 8 | specnaz-kotlin-junit 9 | 1.4 10 | 11 | 12 | 13 | org.specnaz 14 | specnaz 15 | 1.4 16 | 17 | 18 | 19 | org.specnaz 20 | specnaz-kotlin 21 | 1.4 22 | 23 | 24 | 25 | org.specnaz 26 | specnaz-junit 27 | 1.4 28 | 29 | 30 | 31 | org.jetbrains.kotlin 32 | kotlin-stdlib 33 | 1.2.0 34 | provided 35 | 36 | 37 | 38 | junit 39 | junit 40 | 4.12 41 | provided 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/examples/specnaz-custom-dsl-example/src/main/java/org/specnaz/examples/custom_dsl/given_when_then/standalone/GivenWhenThenStandaloneJUnitRunner.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.examples.custom_dsl.given_when_then.standalone; 2 | 3 | import org.junit.runner.Description; 4 | import org.junit.runner.Runner; 5 | import org.junit.runner.notification.RunNotifier; 6 | import org.specnaz.junit.core.SpecnazCoreDslJUnitRunner; 7 | import org.specnaz.junit.utils.Utils; 8 | 9 | public class GivenWhenThenStandaloneJUnitRunner extends Runner { 10 | private final SpecnazCoreDslJUnitRunner coreDslJUnitRunner; 11 | 12 | public GivenWhenThenStandaloneJUnitRunner(Class classs) { 13 | SpecnazGivenWhenThenStandalone specInstance = Utils.instantiateTestClass(classs, 14 | SpecnazGivenWhenThenStandalone.class); 15 | GivenWhenThenCoreWrapper coreWrapper; 16 | try { 17 | coreWrapper = GivenWhenThenRegistry.get(specInstance); 18 | } catch (IllegalArgumentException e) { 19 | throw new IllegalStateException("SpecnazGivenWhenThenStandalone.given() was not called " + 20 | "in the no-argument constructor of " + classs.getSimpleName()); 21 | } 22 | coreWrapper.callSpecification(); 23 | coreDslJUnitRunner = new SpecnazCoreDslJUnitRunner(classs, coreWrapper); 24 | } 25 | 26 | @Override 27 | public Description getDescription() { 28 | return coreDslJUnitRunner.getDescription(); 29 | } 30 | 31 | @Override 32 | public void run(RunNotifier notifier) { 33 | coreDslJUnitRunner.run(notifier); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-testng/resources/specnaz-kotlin-testng-1.4.pom: -------------------------------------------------------------------------------- 1 | 5 | 4.0.0 6 | 7 | org.specnaz 8 | specnaz-kotlin-testng 9 | 1.4 10 | 11 | 12 | 13 | org.specnaz 14 | specnaz 15 | 1.4 16 | 17 | 18 | 19 | org.specnaz 20 | specnaz-kotlin 21 | 1.4 22 | 23 | 24 | 25 | org.specnaz 26 | specnaz-testng 27 | 1.4 28 | 29 | 30 | 31 | org.jetbrains.kotlin 32 | kotlin-stdlib 33 | 1.2.0 34 | provided 35 | 36 | 37 | 38 | org.testng 39 | testng 40 | 6.14.3 41 | provided 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/examples/specnaz-java-examples/src/test/java/FocusedSpec.java: -------------------------------------------------------------------------------- 1 | import org.specnaz.junit.SpecnazJUnit; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | import static org.assertj.core.api.Assertions.fail; 5 | 6 | /** 7 | * This example shows the usage of 'focused' methods - 8 | * {@link org.specnaz.SpecBuilder#fshould} and {@link org.specnaz.SpecBuilder#fshouldThrow}. 9 | */ 10 | public class FocusedSpec extends SpecnazJUnit {{ 11 | describes("A spec with focused tests", it -> { 12 | it.fshould("execute a focused test", () -> { 13 | assertThat(1 + 1).isEqualTo(2); 14 | }); 15 | 16 | it.should("ignore a non-focused test", () -> { 17 | fail("this unfocused test should not have been executed"); 18 | }); 19 | 20 | it.describes("and a subgroup with focused tests", () -> { 21 | it.fshouldThrow(IndexOutOfBoundsException.class, "when executing a focused test in the subgroup", () -> { 22 | int unused = new int[]{1, 2, 3}[3]; 23 | }); 24 | }); 25 | 26 | it.describes("and a subgroup without focused tests", () -> { 27 | it.beginsAll(() -> { 28 | fail("this beginsAll should not have been executed"); 29 | }); 30 | 31 | it.should("not ran either the test, nor any fixture in that group", () -> { 32 | fail("this test should not have been executed"); 33 | }); 34 | 35 | it.endsAll(() -> { 36 | fail("this endsEach should not have been executed"); 37 | }); 38 | }); 39 | }); 40 | }} 41 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/AbstractParametrizedTest.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.SingleTestCase; 4 | import org.specnaz.impl.TestCaseType; 5 | import org.specnaz.utils.TestClosure; 6 | 7 | import java.util.Collection; 8 | import java.util.List; 9 | import java.util.stream.Collectors; 10 | 11 | import static java.lang.String.format; 12 | 13 | public abstract class AbstractParametrizedTest { 14 | public final TestCaseType testCaseType; 15 | private final String description; 16 | private List> params; 17 | 18 | AbstractParametrizedTest(String description, TestCaseType testCaseType) { 19 | this.description = description; 20 | this.testCaseType = testCaseType; 21 | } 22 | 23 | public final void complete(List> params) { 24 | this.params = params; 25 | } 26 | 27 | public final Collection testCases() { 28 | if (params == null) 29 | throw new RuntimeException(format( 30 | "Unfinished parametrized test '%s'. " + 31 | "You need to call the `provided` method on the object returned from `should`", description)); 32 | 33 | return params.stream().map(paramsSet -> testCase(paramsSet)).collect(Collectors.toList()); 34 | } 35 | 36 | protected abstract TestClosure toTestClosure(List params); 37 | 38 | protected abstract SingleTestCase testCase(List params); 39 | 40 | protected final String formatDesc(List params) { 41 | return Conversions.formatParamsDesc(description, params); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/examples/specnaz-java-examples/src/test/java/MockitoExampleSpec.java: -------------------------------------------------------------------------------- 1 | import org.mockito.Mock; 2 | import org.mockito.MockitoAnnotations; 3 | import org.specnaz.junit.SpecnazJUnit; 4 | 5 | import java.util.List; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.mockito.Mockito.when; 9 | 10 | /** 11 | * This example shows how to use Specnaz with 12 | * Mockito. 13 | */ 14 | public class MockitoExampleSpec extends SpecnazJUnit { 15 | @Mock 16 | List listMock; 17 | 18 | { 19 | describes("using Mockito @Mock", it -> { 20 | // if you want to reset the mocks before each test, 21 | /// use beginsEach instead 22 | it.beginsAll(() -> { 23 | MockitoAnnotations.initMocks(this); 24 | }); 25 | 26 | it.should("initialize the @Mocks correctly", () -> { 27 | assertThat(listMock).isNotNull(); 28 | }); 29 | 30 | it.describes("with some stubbing", () -> { 31 | it.beginsEach(() -> { 32 | when(listMock.get(1)).thenReturn(42); 33 | }); 34 | 35 | it.should("return 42 for get(1)", () -> { 36 | assertThat(listMock.get(1)).isEqualTo(42); 37 | }); 38 | }); 39 | 40 | it.describes("resets the @Mocks for each group", () -> { 41 | it.should("return null for get(1)", () -> { 42 | assertThat(listMock.get(1)).isNull(); 43 | }); 44 | }); 45 | }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/specnaz-testng/src/main/java/org/specnaz/testng/SpecnazAlterSuiteListener.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.testng; 2 | 3 | import org.specnaz.Specnaz; 4 | import org.specnaz.params.SpecnazParams; 5 | import org.testng.IAlterSuiteListener; 6 | import org.testng.xml.XmlClass; 7 | import org.testng.xml.XmlSuite; 8 | import org.testng.xml.XmlTest; 9 | 10 | import java.util.List; 11 | import java.util.stream.Collectors; 12 | 13 | public final class SpecnazAlterSuiteListener implements IAlterSuiteListener { 14 | @Override 15 | public void alter(List xmlSuites) { 16 | for (XmlSuite xmlSuite : xmlSuites) { 17 | alterXmlSuite(xmlSuite); 18 | } 19 | } 20 | 21 | private void alterXmlSuite(XmlSuite xmlSuite) { 22 | xmlSuite.setTests(xmlSuite.getTests().stream() 23 | .map(xmlTest -> alterXmlTest(xmlTest)) 24 | .collect(Collectors.toList())); 25 | } 26 | 27 | private XmlTest alterXmlTest(XmlTest xmlTest) { 28 | xmlTest.setClasses(xmlTest.getClasses().stream() 29 | .map(xmlClass -> alterXmlClass(xmlClass)) 30 | .collect(Collectors.toList())); 31 | return xmlTest; 32 | } 33 | 34 | private XmlClass alterXmlClass(XmlClass xmlClass) { 35 | if (isSpecnazClass(xmlClass)) 36 | xmlClass.getExcludedMethods().add(".*describes"); 37 | return xmlClass; 38 | } 39 | 40 | private boolean isSpecnazClass(XmlClass xmlClass) { 41 | return Specnaz.class.isAssignableFrom(xmlClass.getSupportClass()) || 42 | SpecnazParams.class.isAssignableFrom(xmlClass.getSupportClass()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/Params8.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * A simple tuple class holding 8 values. 5 | * You use it to provide parameters to the {@link ParamsExpected8} 6 | * and {@link ParamsExpectedException8} classes. 7 | */ 8 | public final class Params8 { 9 | /** 10 | * Factory method. 11 | * 12 | * @param param1 first parameter 13 | * @param param2 second parameter 14 | * @param param3 third parameter 15 | * @param param4 fourth parameter 16 | * @param param5 fifth parameter 17 | * @param param6 sixth parameter 18 | * @param param7 seventh parameter 19 | * @param param8 eight parameter 20 | * @return a new instance of the {@link Params8} class 21 | */ 22 | public static Params8 p8(P1 param1, P2 param2, 23 | P3 param3, P4 param4, P5 param5, P6 param6, P7 param7, P8 param8) { 24 | return new Params8<>(param1, param2, param3, param4, param5, param6, param7, param8); 25 | } 26 | 27 | public final P1 _1; 28 | public final P2 _2; 29 | public final P3 _3; 30 | public final P4 _4; 31 | public final P5 _5; 32 | public final P6 _6; 33 | public final P7 _7; 34 | public final P8 _8; 35 | 36 | private Params8(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6, P7 param7, P8 param8) { 37 | _1 = param1; 38 | _2 = param2; 39 | _3 = param3; 40 | _4 = param4; 41 | _5 = param5; 42 | _6 = param6; 43 | _7 = param7; 44 | _8 = param8; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpectedSubgroup1.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.params.impl.Conversions; 4 | import org.specnaz.params.impl.ParametrizedSubgroup1; 5 | 6 | import java.util.stream.Stream; 7 | 8 | /** 9 | * The class returned from {@link ParamsSpecBuilder#describes(String, RunnableParams1)}. 10 | * You need call one of the {@code provided} methods on it, 11 | * passing the parameters for each version of the sub-specification. 12 | * 13 | * @see #provided(P...) 14 | * @see #provided(Iterable) 15 | */ 16 | public final class ParamsExpectedSubgroup1

{ 17 | private final ParametrizedSubgroup1

parametrizedSubgroup; 18 | 19 | public ParamsExpectedSubgroup1(ParametrizedSubgroup1

parametrizedSubgroup) { 20 | this.parametrizedSubgroup = parametrizedSubgroup; 21 | } 22 | 23 | /** 24 | * Complete the parametrized sub-specification by providing the parameters 25 | * it will run with. 26 | * 27 | * @param params 28 | * the parameters to create the sub-specifications with 29 | */ 30 | @SafeVarargs 31 | public final void provided(P... params) { 32 | Conversions.complete1d(parametrizedSubgroup, Stream.of(params)); 33 | } 34 | 35 | /** 36 | * Complete the parametrized sub-specification by providing the parameters 37 | * it will run with. 38 | * 39 | * @param params 40 | * the parameters to create the sub-specifications with 41 | */ 42 | public void provided(Iterable params) { 43 | Conversions.complete1d(parametrizedSubgroup, Conversions.iterable2stream(params)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/examples/specnaz-java-examples/src/test/java/ParametrizedSpec.java: -------------------------------------------------------------------------------- 1 | import org.specnaz.params.junit.SpecnazParamsJUnit; 2 | 3 | import static java.lang.String.format; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | import static org.specnaz.params.Params2.p2; 6 | import static org.specnaz.params.Params3.p3; 7 | 8 | /** 9 | * An example of a parametrized Specnaz spec. 10 | */ 11 | public class ParametrizedSpec extends SpecnazParamsJUnit { 12 | { 13 | describes("A parametrized spec", it -> { 14 | it.should("confirm that %1 + %2 = %3", (Integer a, Integer b, Integer c) -> { 15 | assertThat(a + b).isEqualTo(c); 16 | }).provided( 17 | p3(1, 2, 3), 18 | p3(4, 4, 8), 19 | p3(-3, 3, 0), 20 | p3(Integer.MAX_VALUE, 1, Integer.MIN_VALUE) 21 | ); 22 | 23 | it.should("correctly parse '%1' as an Int with radix %2", (String str, Integer radix) -> { 24 | assertThat(Integer.parseInt(str, radix)).isPositive(); 25 | }).provided( 26 | p2("cafe", 16), 27 | p2("G", 17) 28 | ); 29 | 30 | it.describes("with '%1' as the argument", (String str) -> { 31 | it.shouldThrow(NumberFormatException.class, 32 | format("when trying to parse '%s' as an Int with radix %%1", str), (Integer radix) -> { 33 | Integer.parseInt(str, radix); 34 | }).provided(8, 10) 35 | .withMessageContaining(str); 36 | }).provided("cafe", "G"); 37 | }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/impl/AbstractParametrizedSubgroup.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params.impl; 2 | 3 | import org.specnaz.impl.TestCaseType; 4 | 5 | import java.util.Collection; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | 9 | import static java.lang.String.format; 10 | 11 | public abstract class AbstractParametrizedSubgroup { 12 | private final String description; 13 | private final TestCaseType testCaseType; 14 | private List> params; 15 | 16 | public AbstractParametrizedSubgroup(String description, TestCaseType testCaseType) { 17 | this.description = description; 18 | this.testCaseType = testCaseType; 19 | } 20 | 21 | public void complete(List> params) { 22 | this.params = params; 23 | } 24 | 25 | public final Collection instances() { 26 | if (params == null) 27 | throw new RuntimeException(format( 28 | "Unfinished parametrized sub-group '%s'. " + 29 | "You need to call the `provided` method on the object returned from `describes`", description)); 30 | 31 | List ret = new LinkedList<>(); 32 | for (List paramsSet : params) { 33 | ret.add(new ParametrizedSubgroupInstance( 34 | description(paramsSet), toSpecClosure(paramsSet), testCaseType)); 35 | } 36 | return ret; 37 | } 38 | 39 | protected abstract Runnable toSpecClosure(List paramsSet); 40 | 41 | private String description(List paramsSet) { 42 | return Conversions.formatParamsDesc(description, paramsSet); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpectedSubgroup2.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.params.impl.Conversions; 4 | import org.specnaz.params.impl.ParametrizedSubgroup2; 5 | 6 | import java.util.stream.Stream; 7 | 8 | /** 9 | * The class returned from {@link ParamsSpecBuilder#describes(String, RunnableParams2)}. 10 | * You need call one of the {@code provided} methods on it, 11 | * passing the parameters for each version of the sub-specification. 12 | * 13 | * @see #provided(Params2...) 14 | * @see #provided(Iterable) 15 | */ 16 | public final class ParamsExpectedSubgroup2 { 17 | private final ParametrizedSubgroup2 parametrizedSubgroup; 18 | 19 | public ParamsExpectedSubgroup2(ParametrizedSubgroup2 parametrizedSubgroup) { 20 | this.parametrizedSubgroup = parametrizedSubgroup; 21 | } 22 | 23 | /** 24 | * Complete the parametrized sub-specification by providing the parameters 25 | * it will run with. 26 | * 27 | * @param params 28 | * the parameters to create the sub-specifications with 29 | */ 30 | @SafeVarargs 31 | public final void provided(Params2... params) { 32 | Conversions.complete2d(parametrizedSubgroup, Stream.of(params)); 33 | } 34 | 35 | /** 36 | * Complete the parametrized sub-specification by providing the parameters 37 | * it will run with. 38 | * 39 | * @param params 40 | * the parameters to create the sub-specifications with 41 | */ 42 | public void provided(Iterable> params) { 43 | Conversions.complete2d(parametrizedSubgroup, Conversions.iterable2stream(params)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpectedSubgroup3.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.params.impl.ParametrizedSubgroup3; 4 | import org.specnaz.params.impl.Conversions; 5 | 6 | import java.util.stream.Stream; 7 | 8 | /** 9 | * The class returned from {@link ParamsSpecBuilder#describes(String, RunnableParams3)}. 10 | * You need call one of the {@code provided} methods on it, 11 | * passing the parameters for each version of the sub-specification. 12 | * 13 | * @see #provided(Params3...) 14 | * @see #provided(Iterable) 15 | */ 16 | public final class ParamsExpectedSubgroup3 { 17 | private final ParametrizedSubgroup3 parametrizedSubgroup; 18 | 19 | public ParamsExpectedSubgroup3(ParametrizedSubgroup3 parametrizedSubgroup) { 20 | this.parametrizedSubgroup = parametrizedSubgroup; 21 | } 22 | 23 | /** 24 | * Complete the parametrized sub-specification by providing the parameters 25 | * it will run with. 26 | * 27 | * @param params 28 | * the parameters to create the sub-specifications with 29 | */ 30 | @SafeVarargs 31 | public final void provided(Params3... params) { 32 | Conversions.complete3d(parametrizedSubgroup, Stream.of(params)); 33 | } 34 | 35 | /** 36 | * Complete the parametrized sub-specification by providing the parameters 37 | * it will run with. 38 | * 39 | * @param params 40 | * the parameters to create the sub-specifications with 41 | */ 42 | public void provided(Iterable> params) { 43 | Conversions.complete3d(parametrizedSubgroup, Conversions.iterable2stream(params)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/core/SpecnazCoreDsl.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.core; 2 | 3 | import org.specnaz.Specnaz; 4 | import org.specnaz.impl.SpecsRegistry; 5 | import org.specnaz.impl.SpecsRegistryViolation; 6 | 7 | import java.util.function.Consumer; 8 | 9 | /** 10 | * The core DSL of Specnaz. 11 | * You should only use it when writing your custom DSL, like this: 12 | * 13 | *

14 |  * {@code
15 |  *     public interface MyCustomDsl extends SpecnazCoreDsl {
16 |  *         default void myEntryMethod(String description, Consumer specClosure) {
17 |  *             specification(description, specBuilder -> {
18 |  *                 specClosure.accept(new MyDslBuilderAdapter(specBuilder);
19 |  *             }
20 |  *         }
21 |  *      }
22 |  * }
23 |  * 
24 | * 25 | * If you're not writing a custom DSL, use the {@link Specnaz} interface instead. 26 | * 27 | * @see SpecnazCoreDsl#specification 28 | */ 29 | public interface SpecnazCoreDsl { 30 | /** 31 | * The analog of {@link Specnaz#describes} - defines the specification. 32 | * 33 | * @param description 34 | * the top-level description of the spec 35 | * @param specClosure 36 | * the callback that creates the specification 37 | */ 38 | default void specification(String description, Consumer specClosure) { 39 | try { 40 | SpecsRegistry.register(this, description, false, specClosure); 41 | } catch (SpecsRegistryViolation e) { 42 | throw new IllegalStateException("SpecnazCoreDsl.specification() was called multiple times in the " + 43 | "no-argument constructor of " + this.getClass().getSimpleName()); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpectedSubgroup4.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.params.impl.Conversions; 4 | import org.specnaz.params.impl.ParametrizedSubgroup4; 5 | 6 | import java.util.stream.Stream; 7 | 8 | /** 9 | * The class returned from {@link ParamsSpecBuilder#describes(String, RunnableParams4)}. 10 | * You need call one of the {@code provided} methods on it, 11 | * passing the parameters for each version of the sub-specification. 12 | * 13 | * @see #provided(Params4...) 14 | * @see #provided(Iterable) 15 | */ 16 | public final class ParamsExpectedSubgroup4 { 17 | private final ParametrizedSubgroup4 parametrizedSubgroup; 18 | 19 | public ParamsExpectedSubgroup4(ParametrizedSubgroup4 parametrizedSubgroup) { 20 | this.parametrizedSubgroup = parametrizedSubgroup; 21 | } 22 | 23 | /** 24 | * Complete the parametrized sub-specification by providing the parameters 25 | * it will run with. 26 | * 27 | * @param params 28 | * the parameters to create the sub-specifications with 29 | */ 30 | @SafeVarargs 31 | public final void provided(Params4... params) { 32 | Conversions.complete4d(parametrizedSubgroup, Stream.of(params)); 33 | } 34 | 35 | /** 36 | * Complete the parametrized sub-specification by providing the parameters 37 | * it will run with. 38 | * 39 | * @param params 40 | * the parameters to create the sub-specifications with 41 | */ 42 | public void provided(Iterable> params) { 43 | Conversions.complete4d(parametrizedSubgroup, Conversions.iterable2stream(params)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpectedSubgroup5.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.params.impl.Conversions; 4 | import org.specnaz.params.impl.ParametrizedSubgroup5; 5 | 6 | import java.util.stream.Stream; 7 | 8 | /** 9 | * The class returned from {@link ParamsSpecBuilder#describes(String, RunnableParams5)}. 10 | * You need call one of the {@code provided} methods on it, 11 | * passing the parameters for each version of the sub-specification. 12 | * 13 | * @see #provided(Params5...) 14 | * @see #provided(Iterable) 15 | */ 16 | public class ParamsExpectedSubgroup5 { 17 | private final ParametrizedSubgroup5 parametrizedSubgroup; 18 | 19 | public ParamsExpectedSubgroup5(ParametrizedSubgroup5 parametrizedSubgroup) { 20 | this.parametrizedSubgroup = parametrizedSubgroup; 21 | } 22 | 23 | /** 24 | * Complete the parametrized sub-specification by providing the parameters 25 | * it will run with. 26 | * 27 | * @param params 28 | * the parameters to create the sub-specifications with 29 | */ 30 | @SafeVarargs 31 | public final void provided(Params5... params) { 32 | Conversions.complete5d(parametrizedSubgroup, Stream.of(params)); 33 | } 34 | 35 | /** 36 | * Complete the parametrized sub-specification by providing the parameters 37 | * it will run with. 38 | * 39 | * @param params 40 | * the parameters to create the sub-specifications with 41 | */ 42 | public void provided(Iterable> params) { 43 | Conversions.complete5d(parametrizedSubgroup, Conversions.iterable2stream(params)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpectedSubgroup6.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.params.impl.Conversions; 4 | import org.specnaz.params.impl.ParametrizedSubgroup6; 5 | 6 | import java.util.stream.Stream; 7 | 8 | /** 9 | * The class returned from {@link ParamsSpecBuilder#describes(String, RunnableParams6)}. 10 | * You need call one of the {@code provided} methods on it, 11 | * passing the parameters for each version of the sub-specification. 12 | * 13 | * @see #provided(Params6...) 14 | * @see #provided(Iterable) 15 | */ 16 | public final class ParamsExpectedSubgroup6 { 17 | private final ParametrizedSubgroup6 parametrizedSubgroup; 18 | 19 | public ParamsExpectedSubgroup6(ParametrizedSubgroup6 parametrizedSubgroup) { 20 | this.parametrizedSubgroup = parametrizedSubgroup; 21 | } 22 | 23 | /** 24 | * Complete the parametrized sub-specification by providing the parameters 25 | * it will run with. 26 | * 27 | * @param params 28 | * the parameters to create the sub-specifications with 29 | */ 30 | @SafeVarargs 31 | public final void provided(Params6... params) { 32 | Conversions.complete6d(parametrizedSubgroup, Stream.of(params)); 33 | } 34 | 35 | /** 36 | * Complete the parametrized sub-specification by providing the parameters 37 | * it will run with. 38 | * 39 | * @param params 40 | * the parameters to create the sub-specifications with 41 | */ 42 | public void provided(Iterable> params) { 43 | Conversions.complete6d(parametrizedSubgroup, Conversions.iterable2stream(params)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/Params9.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | /** 4 | * A simple tuple class holding 9 values. 5 | * You use it to provide parameters to the {@link ParamsExpected9} 6 | * and {@link ParamsExpectedException9} classes. 7 | */ 8 | public final class Params9 { 9 | /** 10 | * Factory method. 11 | * 12 | * @param param1 first parameter 13 | * @param param2 second parameter 14 | * @param param3 third parameter 15 | * @param param4 fourth parameter 16 | * @param param5 fifth parameter 17 | * @param param6 sixth parameter 18 | * @param param7 seventh parameter 19 | * @param param8 eight parameter 20 | * @param param9 ninth parameter 21 | * @return a new instance of the {@link Params9} class 22 | */ 23 | public static Params9 p9(P1 param1, P2 param2, 24 | P3 param3, P4 param4, P5 param5, P6 param6, P7 param7, P8 param8, P9 param9) { 25 | return new Params9<>(param1, param2, param3, param4, param5, param6, param7, param8, param9); 26 | } 27 | 28 | public final P1 _1; 29 | public final P2 _2; 30 | public final P3 _3; 31 | public final P4 _4; 32 | public final P5 _5; 33 | public final P6 _6; 34 | public final P7 _7; 35 | public final P8 _8; 36 | public final P9 _9; 37 | 38 | private Params9(P1 param1, P2 param2, P3 param3, P4 param4, P5 param5, P6 param6, P7 param7, P8 param8, P9 param9) { 39 | _1 = param1; 40 | _2 = param2; 41 | _3 = param3; 42 | _4 = param4; 43 | _5 = param5; 44 | _6 = param6; 45 | _7 = param7; 46 | _8 = param8; 47 | _9 = param9; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpectedSubgroup7.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.params.impl.Conversions; 4 | import org.specnaz.params.impl.ParametrizedSubgroup7; 5 | 6 | import java.util.stream.Stream; 7 | 8 | /** 9 | * The class returned from {@link ParamsSpecBuilder#describes(String, RunnableParams7)}. 10 | * You need call one of the {@code provided} methods on it, 11 | * passing the parameters for each version of the sub-specification. 12 | * 13 | * @see #provided(Params7...) 14 | * @see #provided(Iterable) 15 | */ 16 | public final class ParamsExpectedSubgroup7 { 17 | private final ParametrizedSubgroup7 parametrizedSubgroup; 18 | 19 | public ParamsExpectedSubgroup7(ParametrizedSubgroup7 parametrizedSubgroup) { 20 | this.parametrizedSubgroup = parametrizedSubgroup; 21 | } 22 | 23 | /** 24 | * Complete the parametrized sub-specification by providing the parameters 25 | * it will run with. 26 | * 27 | * @param params 28 | * the parameters to create the sub-specifications with 29 | */ 30 | @SafeVarargs 31 | public final void provided(Params7... params) { 32 | Conversions.complete7d(parametrizedSubgroup, Stream.of(params)); 33 | } 34 | 35 | /** 36 | * Complete the parametrized sub-specification by providing the parameters 37 | * it will run with. 38 | * 39 | * @param params 40 | * the parameters to create the sub-specifications with 41 | */ 42 | public void provided(Iterable> params) { 43 | Conversions.complete7d(parametrizedSubgroup, Conversions.iterable2stream(params)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/examples/specnaz-custom-dsl-example/src/test/java/GivenWhenThenStackSpec.java: -------------------------------------------------------------------------------- 1 | import org.junit.runner.RunWith; 2 | import org.specnaz.examples.custom_dsl.given_when_then.SpecnazGivenWhenThen; 3 | import org.specnaz.junit.core.SpecnazCoreDslJUnitRunner; 4 | import org.specnaz.utils.IntBox; 5 | 6 | import java.util.Stack; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | import static org.specnaz.utils.IntBox.boxWith; 10 | 11 | @RunWith(SpecnazCoreDslJUnitRunner.class) 12 | public class GivenWhenThenStackSpec implements SpecnazGivenWhenThen { 13 | { 14 | given("a Stack", that -> { 15 | Stack stack = new Stack<>(); 16 | 17 | that.given("with 10 and 20 and 30 pushed on it", 18 | () -> { 19 | stack.push(10); 20 | stack.push(20); 21 | stack.push(30); 22 | }, 23 | () -> { 24 | IntBox top = boxWith(0); 25 | 26 | that.when("pop is called on it", 27 | () -> { 28 | top.$ = stack.pop(); 29 | }, 30 | _that -> { 31 | _that.then("the size of the stack is 2", () -> { 32 | assertThat(stack).hasSize(2); 33 | }); 34 | 35 | _that.then("the popped value is 30", () -> { 36 | assertThat(top.$).isEqualTo(30); 37 | }); 38 | } 39 | ); 40 | } 41 | ); 42 | }); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpectedSubgroup8.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.params.impl.Conversions; 4 | import org.specnaz.params.impl.ParametrizedSubgroup8; 5 | 6 | import java.util.stream.Stream; 7 | 8 | /** 9 | * The class returned from {@link ParamsSpecBuilder#describes(String, RunnableParams8)}. 10 | * You need call one of the {@code provided} methods on it, 11 | * passing the parameters for each version of the sub-specification. 12 | * 13 | * @see #provided(Params8...) 14 | * @see #provided(Iterable) 15 | */ 16 | public final class ParamsExpectedSubgroup8 { 17 | private final ParametrizedSubgroup8 parametrizedSubgroup; 18 | 19 | public ParamsExpectedSubgroup8(ParametrizedSubgroup8 parametrizedSubgroup) { 20 | this.parametrizedSubgroup = parametrizedSubgroup; 21 | } 22 | 23 | /** 24 | * Complete the parametrized sub-specification by providing the parameters 25 | * it will run with. 26 | * 27 | * @param params 28 | * the parameters to create the sub-specifications with 29 | */ 30 | @SafeVarargs 31 | public final void provided(Params8... params) { 32 | Conversions.complete8d(parametrizedSubgroup, Stream.of(params)); 33 | } 34 | 35 | /** 36 | * Complete the parametrized sub-specification by providing the parameters 37 | * it will run with. 38 | * 39 | * @param params 40 | * the parameters to create the sub-specifications with 41 | */ 42 | public void provided(Iterable> params) { 43 | Conversions.complete8d(parametrizedSubgroup, Conversions.iterable2stream(params)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpectedSubgroup9.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.params.impl.Conversions; 4 | import org.specnaz.params.impl.ParametrizedSubgroup9; 5 | 6 | import java.util.stream.Stream; 7 | 8 | /** 9 | * The class returned from {@link ParamsSpecBuilder#describes(String, RunnableParams9)}. 10 | * You need call one of the {@code provided} methods on it, 11 | * passing the parameters for each version of the sub-specification. 12 | * 13 | * @see #provided(Params9...) 14 | * @see #provided(Iterable) 15 | */ 16 | public final class ParamsExpectedSubgroup9 { 17 | private final ParametrizedSubgroup9 parametrizedSubgroup; 18 | 19 | public ParamsExpectedSubgroup9(ParametrizedSubgroup9 parametrizedSubgroup) { 20 | this.parametrizedSubgroup = parametrizedSubgroup; 21 | } 22 | 23 | /** 24 | * Complete the parametrized sub-specification by providing the parameters 25 | * it will run with. 26 | * 27 | * @param params 28 | * the parameters to create the sub-specifications with 29 | */ 30 | @SafeVarargs 31 | public final void provided(Params9... params) { 32 | Conversions.complete9d(parametrizedSubgroup, Stream.of(params)); 33 | } 34 | 35 | /** 36 | * Complete the parametrized sub-specification by providing the parameters 37 | * it will run with. 38 | * 39 | * @param params 40 | * the parameters to create the sub-specifications with 41 | */ 42 | public void provided(Iterable> params) { 43 | Conversions.complete9d(parametrizedSubgroup, Conversions.iterable2stream(params)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/specnaz-testng/src/main/java/org/specnaz/testng/SpecnazTests.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.testng; 2 | 3 | import org.specnaz.impl.ExecutableTestCase; 4 | import org.specnaz.testng.impl.SharedAllsFixtures; 5 | import org.testng.ITest; 6 | import org.testng.SkipException; 7 | import org.testng.annotations.Test; 8 | 9 | public final class SpecnazTests implements ITest { 10 | private final String signature; 11 | private final String descriptionsPrefix; 12 | private final SharedAllsFixtures beforeAlls; 13 | private final ExecutableTestCase testCase; 14 | private final SharedAllsFixtures afterAlls; 15 | 16 | public SpecnazTests(String signature, String descriptionsPrefix, 17 | SharedAllsFixtures beforeAlls, ExecutableTestCase testCase, SharedAllsFixtures afterAlls) { 18 | this.signature = signature; 19 | this.descriptionsPrefix = descriptionsPrefix; 20 | this.beforeAlls = beforeAlls; 21 | this.testCase = testCase; 22 | this.afterAlls = afterAlls; 23 | } 24 | 25 | @Override 26 | public String getTestName() { 27 | return this.descriptionsPrefix + this.testCase.testCase.description; 28 | } 29 | 30 | @Test 31 | public void executeTest() throws Throwable { 32 | if (testCase.isIgnored()) 33 | throw new SkipException("spec marked as ignored"); 34 | 35 | Throwable resultException = beforeAlls.execute(); 36 | 37 | if (resultException == null) 38 | resultException = testCase.execute(); 39 | 40 | Throwable afterAllsException = afterAlls.execute(); 41 | 42 | if (resultException != null) 43 | throw resultException; 44 | else if (afterAllsException != null) 45 | throw afterAllsException; 46 | } 47 | 48 | public String getSignature() { 49 | return signature; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/TestSettings.java: -------------------------------------------------------------------------------- 1 | package org.specnaz; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * Allows you to tweak the settings of an individual test. 8 | * An instance of this class is returned from {@link SpecBuilder#should}. 9 | * 10 | * @see #usingMethod 11 | */ 12 | public final class TestSettings { 13 | private Method method; 14 | 15 | /** 16 | * Sets the {@link Method} used for this test. 17 | * This is mainly useful for external integrations - 18 | * for example, Spring's JUnit Rules use annotations on the test 19 | * method for different behaviors. 20 | *

21 | * There's a helper included with Specnaz that tries to make finding the parameter 22 | * to pass to this method easier, {@link org.specnaz.utils.Utils#findMethod}. 23 | * 24 | * @param method the {@link Method} to use 25 | * @return {@code this} 26 | * @see org.specnaz.utils.Utils#findMethod 27 | */ 28 | public TestSettings usingMethod(Method method) { 29 | this.method = method; 30 | return this; 31 | } 32 | 33 | /** 34 | * This is a wrapper class used in the implementation of Specnaz. 35 | * You never need it when writing tests, 36 | * it's just an implementation detail. 37 | */ 38 | public static final class Wrapper { 39 | private final TestSettings inner; 40 | 41 | public Wrapper(TestSettings inner) { 42 | this.inner = inner; 43 | } 44 | 45 | public Method method() { 46 | return inner.method; 47 | } 48 | 49 | public Annotation[] annotations() { 50 | Method method = method(); 51 | return method == null 52 | ? new Annotation[]{} 53 | : method.getAnnotations(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/specnaz-testng/src/test/java/org/specnaz/testng/SpecnazTestNgSpecWithBefores.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.testng; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Test; 5 | 6 | @Test 7 | public class SpecnazTestNgSpecWithBefores implements SpecnazFactoryTestNG { 8 | int counter = 0; 9 | 10 | { 11 | describes("A spec with befores", it -> { 12 | it.beginsAll(() -> { 13 | counter++; 14 | }); 15 | 16 | it.beginsEach(() -> { 17 | counter++; 18 | }); 19 | 20 | it.should("run the beginsEach to increment the counter by 1", () -> { 21 | Assert.assertEquals(counter, 2); 22 | }); 23 | 24 | it.should("also run the endsEach to decrement the counter by 1 ", () -> { 25 | Assert.assertEquals(counter, 2); 26 | }); 27 | 28 | it.shouldThrow(ArithmeticException.class, "when dividing by counter - 2", () -> { 29 | int unused = 1 / (counter - 2); 30 | }); 31 | 32 | it.endsEach(() -> { 33 | counter--; 34 | }); 35 | 36 | it.endsAll(() -> { 37 | counter--; 38 | }); 39 | 40 | it.describes("with a sub-specification", () -> { 41 | it.beginsAll(() -> { 42 | counter++; 43 | }); 44 | 45 | it.beginsEach(() -> { 46 | counter++; 47 | }); 48 | 49 | it.should("run the parent fixtures in the child test", () -> { 50 | Assert.assertEquals(counter, 4); 51 | }); 52 | 53 | it.endsEach(() -> { 54 | counter--; 55 | }); 56 | 57 | it.endsAll(() -> { 58 | counter--; 59 | }); 60 | }); 61 | }); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpected1.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.params.impl.Conversions; 5 | import org.specnaz.params.impl.ParametrizedPositiveTest1; 6 | 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * The class returned from {@link ParamsSpecBuilder#should(String, TestClosureParams1)}. 11 | * You need to call one of the {@code provided} methods on it, 12 | * passing the parameters for the test to run with. 13 | * 14 | * @see #provided(P...) 15 | * @see #provided(Iterable) 16 | */ 17 | public final class ParamsExpected1

{ 18 | private final ParametrizedPositiveTest1

parametrizedTest; 19 | 20 | public ParamsExpected1(ParametrizedPositiveTest1

parametrizedTest) { 21 | this.parametrizedTest = parametrizedTest; 22 | } 23 | 24 | /** 25 | * Complete the parametrized test by providing the parameters 26 | * it will run with. 27 | * 28 | * @param params 29 | * the parameters to run the test with 30 | * @return 31 | * an instance of the {@link TestSettings} class, like a regular 32 | * {@link org.specnaz.SpecBuilder#should} method would 33 | */ 34 | @SafeVarargs 35 | public final TestSettings provided(P... params) { 36 | return Conversions.complete1p(parametrizedTest, Stream.of(params)); 37 | } 38 | 39 | /** 40 | * Complete the parametrized test by providing the parameters 41 | * it will run with. 42 | * 43 | * @param params 44 | * the parameters to run the test with 45 | * @return 46 | * an instance of the {@link TestSettings} class, like a regular 47 | * {@link org.specnaz.SpecBuilder#should} method would 48 | */ 49 | public final TestSettings provided(Iterable params) { 50 | return Conversions.complete1p(parametrizedTest, Conversions.iterable2stream(params)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/examples/specnaz-custom-dsl-example/src/test/java/standalone/GivenWhenThenStandaloneStackSpec.java: -------------------------------------------------------------------------------- 1 | package standalone; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.specnaz.examples.custom_dsl.given_when_then.standalone.GivenWhenThenStandaloneJUnitRunner; 5 | import org.specnaz.examples.custom_dsl.given_when_then.standalone.SpecnazGivenWhenThenStandalone; 6 | import org.specnaz.utils.IntBox; 7 | 8 | import java.util.Stack; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | import static org.specnaz.utils.IntBox.boxWith; 12 | 13 | @RunWith(GivenWhenThenStandaloneJUnitRunner.class) 14 | public class GivenWhenThenStandaloneStackSpec implements SpecnazGivenWhenThenStandalone { 15 | { 16 | given("a Stack", that -> { 17 | Stack stack = new Stack<>(); 18 | 19 | that.given("with 10 and 20 and 30 pushed on it", 20 | () -> { 21 | stack.push(10); 22 | stack.push(20); 23 | stack.push(30); 24 | }, 25 | () -> { 26 | IntBox top = boxWith(0); 27 | 28 | that.when("pop is called on it", 29 | () -> { 30 | top.$ = stack.pop(); 31 | }, 32 | _that -> { 33 | _that.then("the size of the stack is 2", () -> { 34 | assertThat(stack).hasSize(2); 35 | }); 36 | 37 | _that.then("the popped value is 30", () -> { 38 | assertThat(top.$).isEqualTo(30); 39 | }); 40 | } 41 | ); 42 | } 43 | ); 44 | }); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpected2.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.params.impl.Conversions; 5 | import org.specnaz.params.impl.ParametrizedPositiveTest2; 6 | 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * The class returned from {@link ParamsSpecBuilder#should(String, TestClosureParams2)}. 11 | * You need to call one of the {@code provided} methods on it, 12 | * passing the parameters for the test to run with. 13 | * 14 | * @see #provided(Params2...) 15 | * @see #provided(Iterable) 16 | */ 17 | public final class ParamsExpected2 { 18 | private final ParametrizedPositiveTest2 parametrizedTest; 19 | 20 | public ParamsExpected2(ParametrizedPositiveTest2 parametrizedTest) { 21 | this.parametrizedTest = parametrizedTest; 22 | } 23 | 24 | /** 25 | * Complete the parametrized test by providing the parameters 26 | * it will run with. 27 | * 28 | * @param params 29 | * the parameters to run the test with 30 | * @return 31 | * an instance of the {@link TestSettings} class, like a regular 32 | * {@link org.specnaz.SpecBuilder#should} method would 33 | */ 34 | @SafeVarargs 35 | public final TestSettings provided(Params2... params) { 36 | return Conversions.complete2p(parametrizedTest, Stream.of(params)); 37 | } 38 | 39 | /** 40 | * Complete the parametrized test by providing the parameters 41 | * it will run with. 42 | * 43 | * @param params 44 | * the parameters to run the test with 45 | * @return 46 | * an instance of the {@link TestSettings} class, like a regular 47 | * {@link org.specnaz.SpecBuilder#should} method would 48 | */ 49 | public final TestSettings provided(Iterable> params) { 50 | return Conversions.complete2p(parametrizedTest, Conversions.iterable2stream(params)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpected3.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.params.impl.Conversions; 5 | import org.specnaz.params.impl.ParametrizedPositiveTest3; 6 | 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * The class returned from {@link ParamsSpecBuilder#should(String, TestClosureParams3)}. 11 | * You need to call one of the {@code provided} methods on it, 12 | * passing the parameters for the test to run with. 13 | * 14 | * @see #provided(Params3...) 15 | * @see #provided(Iterable) 16 | */ 17 | public final class ParamsExpected3 { 18 | private final ParametrizedPositiveTest3 parametrizedTest; 19 | 20 | public ParamsExpected3(ParametrizedPositiveTest3 parametrizedTest) { 21 | this.parametrizedTest = parametrizedTest; 22 | } 23 | 24 | /** 25 | * Complete the parametrized test by providing the parameters 26 | * it will run with. 27 | * 28 | * @param params 29 | * the parameters to run the test with 30 | * @return 31 | * an instance of the {@link TestSettings} class, like a regular 32 | * {@link org.specnaz.SpecBuilder#should} method would 33 | */ 34 | @SafeVarargs 35 | public final TestSettings provided(Params3... params) { 36 | return Conversions.complete3p(parametrizedTest, Stream.of(params)); 37 | } 38 | 39 | /** 40 | * Complete the parametrized test by providing the parameters 41 | * it will run with. 42 | * 43 | * @param params 44 | * the parameters to run the test with 45 | * @return 46 | * an instance of the {@link TestSettings} class, like a regular 47 | * {@link org.specnaz.SpecBuilder#should} method would 48 | */ 49 | public TestSettings provided(Iterable> params) { 50 | return Conversions.complete3p(parametrizedTest, Conversions.iterable2stream(params)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpected4.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.params.impl.Conversions; 5 | import org.specnaz.params.impl.ParametrizedPositiveTest4; 6 | 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * The class returned from {@link ParamsSpecBuilder#should(String, TestClosureParams4)}. 11 | * You need to call one of the {@code provided} methods on it, 12 | * passing the parameters for the test to run with. 13 | * 14 | * @see #provided(Params4...) 15 | * @see #provided(Iterable) 16 | */ 17 | public final class ParamsExpected4 { 18 | private final ParametrizedPositiveTest4 parametrizedTest; 19 | 20 | public ParamsExpected4(ParametrizedPositiveTest4 parametrizedTest) { 21 | this.parametrizedTest = parametrizedTest; 22 | } 23 | 24 | /** 25 | * Complete the parametrized test by providing the parameters 26 | * it will run with. 27 | * 28 | * @param params 29 | * the parameters to run the test with 30 | * @return 31 | * an instance of the {@link TestSettings} class, like a regular 32 | * {@link org.specnaz.SpecBuilder#should} method would 33 | */ 34 | @SafeVarargs 35 | public final TestSettings provided(Params4... params) { 36 | return Conversions.complete4p(parametrizedTest, Stream.of(params)); 37 | } 38 | 39 | /** 40 | * Complete the parametrized test by providing the parameters 41 | * it will run with. 42 | * 43 | * @param params 44 | * the parameters to run the test with 45 | * @return 46 | * an instance of the {@link TestSettings} class, like a regular 47 | * {@link org.specnaz.SpecBuilder#should} method would 48 | */ 49 | public TestSettings provided(Iterable> params) { 50 | return Conversions.complete4p(parametrizedTest, Conversions.iterable2stream(params)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/specnaz-junit/src/main/java/org/specnaz/junit/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.junit.utils; 2 | 3 | import static java.lang.String.format; 4 | 5 | /** 6 | * A static utility class. 7 | * 8 | * @see Utils#instantiateTestClass 9 | */ 10 | public final class Utils { 11 | /** 12 | * Instantiates the given {@code testClass} with the no-argument constructor, using reflection. 13 | * 14 | * @param testClass 15 | * the class of the test object 16 | * @param targetClass 17 | * the desired class of {@code testClass} 18 | * @param 19 | * the type of the instance that we want to instantiate 20 | * @return 21 | * an object of type {@code T} 22 | * @throws IllegalArgumentException 23 | * if either {@code testClass} is not a subtype of {@code targetClass}, or 24 | * if the instantiation with the no-argument constructor failed 25 | * (the root cause will be available via the {@link Throwable#getCause} method of the exception) 26 | */ 27 | public static T instantiateTestClass(Class testClass, Class targetClass) throws IllegalArgumentException { 28 | String className = testClass.getSimpleName(); 29 | if (targetClass.isAssignableFrom(testClass)) { 30 | Class specClass = testClass.asSubclass(targetClass); 31 | try { 32 | return specClass.newInstance(); 33 | } catch (Exception e) { 34 | throw new IllegalArgumentException(format( 35 | "Could not instantiate test class '%s' with no-argument constructor", className), 36 | e); 37 | } 38 | } else { 39 | throw new IllegalArgumentException(format( 40 | "Expected test class to be a subtype of '%s'; %s is not", targetClass.getSimpleName(), className)); 41 | } 42 | } 43 | 44 | Utils() { 45 | throw new UnsupportedOperationException("Cannot instantiate Utils"); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpected5.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.params.impl.Conversions; 5 | import org.specnaz.params.impl.ParametrizedPositiveTest5; 6 | 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * The class returned from {@link ParamsSpecBuilder#should(String, TestClosureParams5)}. 11 | * You need to call one of the {@code provided} methods on it, 12 | * passing the parameters for the test to run with. 13 | * 14 | * @see #provided(Params5...) 15 | * @see #provided(Iterable) 16 | */ 17 | public final class ParamsExpected5 { 18 | private final ParametrizedPositiveTest5 parametrizedTest; 19 | 20 | public ParamsExpected5(ParametrizedPositiveTest5 parametrizedTest) { 21 | this.parametrizedTest = parametrizedTest; 22 | } 23 | 24 | /** 25 | * Complete the parametrized test by providing the parameters 26 | * it will run with. 27 | * 28 | * @param params 29 | * the parameters to run the test with 30 | * @return 31 | * an instance of the {@link TestSettings} class, like a regular 32 | * {@link org.specnaz.SpecBuilder#should} method would 33 | */ 34 | @SafeVarargs 35 | public final TestSettings provided(Params5... params) { 36 | return Conversions.complete5p(parametrizedTest, Stream.of(params)); 37 | } 38 | 39 | /** 40 | * Complete the parametrized test by providing the parameters 41 | * it will run with. 42 | * 43 | * @param params 44 | * the parameters to run the test with 45 | * @return 46 | * an instance of the {@link TestSettings} class, like a regular 47 | * {@link org.specnaz.SpecBuilder#should} method would 48 | */ 49 | public TestSettings provided(Iterable> params) { 50 | return Conversions.complete5p(parametrizedTest, Conversions.iterable2stream(params)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.utils; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * Some static utility methods helpful when writing tests in Specnaz. 7 | * 8 | * @see #findMethod 9 | */ 10 | public final class Utils { 11 | /** 12 | * A shorthand useful when setting the test method with {@link org.specnaz.TestSettings#usingMethod}. 13 | * Allows you to easily refer to a method in the specification class by name. 14 | * You call it something like this: 15 | * 16 | *


17 |      * public class SomeSpec extends SpecnazJUnit {
18 |      *       {
19 |      *           describes("some example tests", it -> {
20 |      *               it.should("correctly find the method", () -> {
21 |      *                   // test body...
22 |      *               }).usingMethod(Utils.findMethod(this, "someMethod"));
23 |      *           });
24 |      *       }
25 |      *
26 |      *       @DirtiesContext
27 |      *       public void someMethod() {
28 |      *       }
29 |      * }
30 |      * 
31 | * 32 | * @param spec 33 | * the spec instance 34 | * @param methodName 35 | * the name of the method to find 36 | * @param parameterTypes 37 | * the types of parameters of the method to find 38 | * @return the desired {@link Method} 39 | * @throws IllegalArgumentException 40 | * if the desired method could not be found 41 | * @see org.specnaz.TestSettings#usingMethod 42 | */ 43 | public static Method findMethod(Object spec, String methodName, Class... parameterTypes) 44 | throws IllegalArgumentException { 45 | try { 46 | return spec.getClass().getMethod(methodName, parameterTypes); 47 | } catch (NoSuchMethodException e) { 48 | throw new IllegalArgumentException(e); 49 | } 50 | } 51 | 52 | Utils() { 53 | throw new UnsupportedOperationException("Cannot instantiate Utils"); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpected6.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.params.impl.Conversions; 5 | import org.specnaz.params.impl.ParametrizedPositiveTest6; 6 | 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * The class returned from {@link ParamsSpecBuilder#should(String, TestClosureParams6)}. 11 | * You need to call one of the {@code provided} methods on it, 12 | * passing the parameters for the test to run with. 13 | * 14 | * @see #provided(Params6...) 15 | * @see #provided(Iterable) 16 | */ 17 | public final class ParamsExpected6 { 18 | private final ParametrizedPositiveTest6 parametrizedTest; 19 | 20 | public ParamsExpected6(ParametrizedPositiveTest6 parametrizedTest) { 21 | this.parametrizedTest = parametrizedTest; 22 | } 23 | 24 | /** 25 | * Complete the parametrized test by providing the parameters 26 | * it will run with. 27 | * 28 | * @param params 29 | * the parameters to run the test with 30 | * @return 31 | * an instance of the {@link TestSettings} class, like a regular 32 | * {@link org.specnaz.SpecBuilder#should} method would 33 | */ 34 | @SafeVarargs 35 | public final TestSettings provided(Params6... params) { 36 | return Conversions.complete6p(parametrizedTest, Stream.of(params)); 37 | } 38 | 39 | /** 40 | * Complete the parametrized test by providing the parameters 41 | * it will run with. 42 | * 43 | * @param params 44 | * the parameters to run the test with 45 | * @return 46 | * an instance of the {@link TestSettings} class, like a regular 47 | * {@link org.specnaz.SpecBuilder#should} method would 48 | */ 49 | public TestSettings provided(Iterable> params) { 50 | return Conversions.complete6p(parametrizedTest, Conversions.iterable2stream(params)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpected7.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.params.impl.Conversions; 5 | import org.specnaz.params.impl.ParametrizedPositiveTest7; 6 | 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * The class returned from {@link ParamsSpecBuilder#should(String, TestClosureParams7)}. 11 | * You need to call one of the {@code provided} methods on it, 12 | * passing the parameters for the test to run with. 13 | * 14 | * @see #provided(Params7...) 15 | * @see #provided(Iterable) 16 | */ 17 | public final class ParamsExpected7 { 18 | private final ParametrizedPositiveTest7 parametrizedTest; 19 | 20 | public ParamsExpected7(ParametrizedPositiveTest7 parametrizedTest) { 21 | this.parametrizedTest = parametrizedTest; 22 | } 23 | 24 | /** 25 | * Complete the parametrized test by providing the parameters 26 | * it will run with. 27 | * 28 | * @param params 29 | * the parameters to run the test with 30 | * @return 31 | * an instance of the {@link TestSettings} class, like a regular 32 | * {@link org.specnaz.SpecBuilder#should} method would 33 | */ 34 | @SafeVarargs 35 | public final TestSettings provided(Params7... params) { 36 | return Conversions.complete7p(parametrizedTest, Stream.of(params)); 37 | } 38 | 39 | /** 40 | * Complete the parametrized test by providing the parameters 41 | * it will run with. 42 | * 43 | * @param params 44 | * the parameters to run the test with 45 | * @return 46 | * an instance of the {@link TestSettings} class, like a regular 47 | * {@link org.specnaz.SpecBuilder#should} method would 48 | */ 49 | public TestSettings provided(Iterable> params) { 50 | return Conversions.complete7p(parametrizedTest, Conversions.iterable2stream(params)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpectedException1.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.params.impl.Conversions; 4 | import org.specnaz.params.impl.ParametrizedExceptionTest1; 5 | import org.specnaz.utils.ThrowableExpectations; 6 | 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * The class returned from {@link ParamsSpecBuilder#shouldThrow(Class, String, TestClosureParams1)}. 11 | * You need to call one of the {@code provided} methods on it, 12 | * passing the parameters for the test to run with. 13 | * 14 | * @see #provided(P...) 15 | * @see #provided(Iterable) 16 | */ 17 | public final class ParamsExpectedException1 { 18 | private final ParametrizedExceptionTest1 parametrizedTest; 19 | 20 | public ParamsExpectedException1(ParametrizedExceptionTest1 parametrizedTest) { 21 | this.parametrizedTest = parametrizedTest; 22 | } 23 | 24 | /** 25 | * Complete the parametrized test by providing the parameters 26 | * it will run with. 27 | * 28 | * @param params 29 | * the parameters to run the test with 30 | * @return 31 | * an instance of the {@link ThrowableExpectations} class, like a regular 32 | * {@link org.specnaz.SpecBuilder#shouldThrow} method would 33 | */ 34 | @SafeVarargs 35 | public final ThrowableExpectations provided(P... params) { 36 | return Conversions.complete1e(parametrizedTest, Stream.of(params)); 37 | } 38 | 39 | /** 40 | * Complete the parametrized test by providing the parameters 41 | * it will run with. 42 | * 43 | * @param params 44 | * the parameters to run the test with 45 | * @return 46 | * an instance of the {@link ThrowableExpectations} class, like a regular 47 | * {@link org.specnaz.SpecBuilder#shouldThrow} method would 48 | */ 49 | public final ThrowableExpectations provided(Iterable params) { 50 | return Conversions.complete1e(parametrizedTest, Conversions.iterable2stream(params)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpected8.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.params.impl.Conversions; 5 | import org.specnaz.params.impl.ParametrizedPositiveTest8; 6 | 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * The class returned from {@link ParamsSpecBuilder#should(String, TestClosureParams8)}. 11 | * You need to call one of the {@code provided} methods on it, 12 | * passing the parameters for the test to run with. 13 | * 14 | * @see #provided(Params8...) 15 | * @see #provided(Iterable) 16 | */ 17 | public final class ParamsExpected8 { 18 | private final ParametrizedPositiveTest8 parametrizedTest; 19 | 20 | public ParamsExpected8(ParametrizedPositiveTest8 parametrizedTest) { 21 | this.parametrizedTest = parametrizedTest; 22 | } 23 | 24 | /** 25 | * Complete the parametrized test by providing the parameters 26 | * it will run with. 27 | * 28 | * @param params 29 | * the parameters to run the test with 30 | * @return 31 | * an instance of the {@link TestSettings} class, like a regular 32 | * {@link org.specnaz.SpecBuilder#should} method would 33 | */ 34 | @SafeVarargs 35 | public final TestSettings provided(Params8... params) { 36 | return Conversions.complete8p(parametrizedTest, Stream.of(params)); 37 | } 38 | 39 | /** 40 | * Complete the parametrized test by providing the parameters 41 | * it will run with. 42 | * 43 | * @param params 44 | * the parameters to run the test with 45 | * @return 46 | * an instance of the {@link TestSettings} class, like a regular 47 | * {@link org.specnaz.SpecBuilder#should} method would 48 | */ 49 | public TestSettings provided(Iterable> params) { 50 | return Conversions.complete8p(parametrizedTest, Conversions.iterable2stream(params)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/specnaz-kotlin-testng/src/main/kotlin/org/specnaz/kotlin/testng/SpecnazKotlinFactoryTestNG.kt: -------------------------------------------------------------------------------- 1 | package org.specnaz.kotlin.testng 2 | 3 | import org.specnaz.impl.SpecsRegistryViolation 4 | import org.specnaz.kotlin.SpecnazKotlin 5 | import org.specnaz.testng.SpecnazFactoryTestNG 6 | import org.specnaz.testng.impl.SpecnazTestNgSpecFactory 7 | import org.testng.annotations.Factory 8 | 9 | /** 10 | * The Kotlin equivalent of [SpecnazFactoryTestNG]. 11 | * You use it identically as [SpecnazFactoryTestNG]: 12 | * your class must implement this interface 13 | * (it has one, default, method) 14 | * and be annotated with [org.testng.annotations.Test]. 15 | * Other than that, the specification looks like any other 16 | * [SpecnazKotlin] spec: the [SpecnazKotlin.describes] 17 | * method must be called in the public, no-argument 18 | * constructor exactly once, with the body of the specification. 19 | * Example: 20 | * 21 | * ```kotlin 22 | * import org.specnaz.kotlin.testng.SpecnazKotlinFactoryTestNG 23 | * import org.testng.annotations.Test 24 | * 25 | * @Test 26 | * class MySpec : SpecnazKotlinFactoryTestNG { init { 27 | * describes("My specification") { 28 | * // use 'it' here to construct the specification... 29 | * } 30 | * }} 31 | * ``` 32 | * 33 | * If your test class does not need to extend a particular class, 34 | * you can use the [SpecnazKotlinTestNG] helper class 35 | * to make the test setup more concise (and save one level of indentation). 36 | * 37 | * @see SpecnazFactoryTestNG 38 | * @see SpecnazKotlin 39 | * @see SpecnazKotlinTestNG 40 | */ 41 | interface SpecnazKotlinFactoryTestNG : SpecnazKotlin { 42 | /** 43 | * The Kotlin equivalent of [SpecnazFactoryTestNG.specs]. 44 | */ 45 | @Factory 46 | fun specs(): Array { 47 | try { 48 | return SpecnazTestNgSpecFactory.specs(this) 49 | } catch (e: SpecsRegistryViolation) { 50 | throw IllegalStateException("SpecnazKotlin.describes() was never called in the " + 51 | "no-argument constructor of " + this.javaClass.simpleName) 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpected9.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.TestSettings; 4 | import org.specnaz.params.impl.Conversions; 5 | import org.specnaz.params.impl.ParametrizedPositiveTest9; 6 | 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * The class returned from {@link ParamsSpecBuilder#should(String, TestClosureParams9)}. 11 | * You need to call one of the {@code provided} methods on it, 12 | * passing the parameters for the test to run with. 13 | * 14 | * @see #provided(Params9...) 15 | * @see #provided(Iterable) 16 | */ 17 | public final class ParamsExpected9 { 18 | private final ParametrizedPositiveTest9 parametrizedTest; 19 | 20 | public ParamsExpected9(ParametrizedPositiveTest9 parametrizedTest) { 21 | this.parametrizedTest = parametrizedTest; 22 | } 23 | 24 | /** 25 | * Complete the parametrized test by providing the parameters 26 | * it will run with. 27 | * 28 | * @param params 29 | * the parameters to run the test with 30 | * @return 31 | * an instance of the {@link TestSettings} class, like a regular 32 | * {@link org.specnaz.SpecBuilder#should} method would 33 | */ 34 | @SafeVarargs 35 | public final TestSettings provided(Params9... params) { 36 | return Conversions.complete9p(parametrizedTest, Stream.of(params)); 37 | } 38 | 39 | /** 40 | * Complete the parametrized test by providing the parameters 41 | * it will run with. 42 | * 43 | * @param params 44 | * the parameters to run the test with 45 | * @return 46 | * an instance of the {@link TestSettings} class, like a regular 47 | * {@link org.specnaz.SpecBuilder#should} method would 48 | */ 49 | public TestSettings provided(Iterable> params) { 50 | return Conversions.complete9p(parametrizedTest, Conversions.iterable2stream(params)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/specnaz/src/main/java/org/specnaz/params/ParamsExpectedException2.java: -------------------------------------------------------------------------------- 1 | package org.specnaz.params; 2 | 3 | import org.specnaz.params.impl.Conversions; 4 | import org.specnaz.params.impl.ParametrizedExceptionTest2; 5 | import org.specnaz.utils.ThrowableExpectations; 6 | 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * The class returned from {@link ParamsSpecBuilder#shouldThrow(Class, String, TestClosureParams2)}. 11 | * You need to call one of the {@code provided} methods on it, 12 | * passing the parameters for the test to run with. 13 | * 14 | * @see #provided(Params2...) 15 | * @see #provided(Iterable) 16 | */ 17 | public final class ParamsExpectedException2 { 18 | private final ParametrizedExceptionTest2 parametrizedTest; 19 | 20 | public ParamsExpectedException2(ParametrizedExceptionTest2 parametrizedTest) { 21 | this.parametrizedTest = parametrizedTest; 22 | } 23 | 24 | /** 25 | * Complete the parametrized test by providing the parameters 26 | * it will run with. 27 | * 28 | * @param params 29 | * the parameters to run the test with 30 | * @return 31 | * an instance of the {@link ThrowableExpectations} class, like a regular 32 | * {@link org.specnaz.SpecBuilder#shouldThrow} method would 33 | */ 34 | @SafeVarargs 35 | public final ThrowableExpectations provided(Params2... params) { 36 | return Conversions.complete2e(parametrizedTest, Stream.of(params)); 37 | } 38 | 39 | /** 40 | * Complete the parametrized test by providing the parameters 41 | * it will run with. 42 | * 43 | * @param params 44 | * the parameters to run the test with 45 | * @return 46 | * an instance of the {@link ThrowableExpectations} class, like a regular 47 | * {@link org.specnaz.SpecBuilder#shouldThrow} method would 48 | */ 49 | public final ThrowableExpectations provided(Iterable> params) { 50 | return Conversions.complete2e(parametrizedTest, Conversions.iterable2stream(params)); 51 | } 52 | } 53 | --------------------------------------------------------------------------------