├── .gitignore ├── .travis.yml ├── oleaster-runner ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── mscharhag │ │ │ └── oleaster │ │ │ └── runner │ │ │ ├── PendingInvokable.java │ │ │ ├── OleasterTest.java │ │ │ ├── StaticSupportingSuiteBuilder.java │ │ │ ├── Invokable.java │ │ │ ├── suite │ │ │ ├── SuiteDefinition.java │ │ │ ├── Spec.java │ │ │ ├── SuiteDefinitionEvaluator.java │ │ │ ├── Suite.java │ │ │ └── SuiteBuilder.java │ │ │ ├── OleasterRunner.java │ │ │ └── StaticRunnerSupport.java │ └── test │ │ └── java │ │ └── com │ │ └── mscharhag │ │ └── oleaster │ │ └── runner │ │ ├── FocusedSpecTest.java │ │ ├── AssertUtil.java │ │ ├── PendingSpecTest.java │ │ ├── SpecTest.java │ │ ├── OleasterRunnerTest.java │ │ ├── SuiteBuilderTest.java │ │ ├── HandlerTest.java │ │ └── SuiteDefinitionEvaluatorTest.java ├── pom.xml └── README.md ├── oleaster-examples ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── mscharhag │ │ │ └── oleaster │ │ │ └── examples │ │ │ ├── Track.java │ │ │ ├── AudioPlayer.java │ │ │ └── Person.java │ └── test │ │ └── java │ │ └── com │ │ └── mscharhag │ │ └── oleaster │ │ └── examples │ │ ├── OleasterIntroductionTest.java │ │ ├── RunnerExamplesTest.java │ │ ├── AudioPlayerExampleTest.java │ │ └── MatcherExamplesTest.java └── pom.xml ├── oleaster-matcher ├── pom.xml ├── src │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── mscharhag │ │ │ └── oleaster │ │ │ └── matcher │ │ │ ├── TestUtil.java │ │ │ ├── matchers │ │ │ ├── BooleanMatcherTest.java │ │ │ ├── ExceptionMatcherTest.java │ │ │ ├── StringMatcherTest.java │ │ │ ├── ObjectMatcherTest.java │ │ │ ├── IntegerNumberMatcherTest.java │ │ │ ├── datetime │ │ │ │ └── DateMatcherTest.java │ │ │ ├── FloatingPointNumberMatcherTest.java │ │ │ ├── CollectionMatcherTest.java │ │ │ └── MapMatcherTest.java │ │ │ └── MatchersTest.java │ └── main │ │ └── java │ │ └── com │ │ └── mscharhag │ │ └── oleaster │ │ └── matcher │ │ ├── util │ │ ├── Arguments.java │ │ └── Expectations.java │ │ ├── matchers │ │ ├── BooleanMatcher.java │ │ ├── ObjectMatcher.java │ │ ├── datetime │ │ │ └── DateMatcher.java │ │ ├── IntegerNumberMatcher.java │ │ ├── CollectionMatcher.java │ │ ├── ExceptionMatcher.java │ │ ├── StringMatcher.java │ │ ├── MapMatcher.java │ │ └── FloatingPointNumberMatcher.java │ │ └── Matchers.java └── README.md ├── pom.xml ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .classpath/ 3 | .project/ 4 | .settings/ 5 | .idea/ 6 | *.iml -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | script: mvn clean test 3 | after_failure: 4 | - "cat ./target/surefire-reports/*.xml" 5 | jdk: 6 | - oraclejdk8 7 | -------------------------------------------------------------------------------- /oleaster-runner/src/main/java/com/mscharhag/oleaster/runner/PendingInvokable.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.runner; 2 | 3 | public interface PendingInvokable extends Invokable {} 4 | -------------------------------------------------------------------------------- /oleaster-examples/src/main/java/com/mscharhag/oleaster/examples/Track.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.examples; 2 | 3 | public class Track { 4 | 5 | private String title; 6 | 7 | public Track(String title) { 8 | this.title = title; 9 | } 10 | 11 | @Override 12 | public boolean equals(Object o) { 13 | if (this == o) return true; 14 | if (o == null || getClass() != o.getClass()) return false; 15 | return title.equals(((Track)o).title); 16 | } 17 | 18 | @Override 19 | public int hashCode() { 20 | return title.hashCode(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /oleaster-examples/src/main/java/com/mscharhag/oleaster/examples/AudioPlayer.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.examples; 2 | 3 | import com.mscharhag.oleaster.examples.Track; 4 | 5 | public class AudioPlayer { 6 | 7 | private PlayerState state; 8 | private Track currentlyPlayedTrack; 9 | 10 | public AudioPlayer() { 11 | this.state = PlayerState.stopped; 12 | this.currentlyPlayedTrack = null; 13 | } 14 | 15 | public void play(Track track) { 16 | this.state = PlayerState.playing; 17 | this.currentlyPlayedTrack = track; 18 | } 19 | 20 | public PlayerState getState() { 21 | return this.state; 22 | } 23 | 24 | public Track getCurrentlyPlayedTrack() { 25 | return this.currentlyPlayedTrack; 26 | } 27 | 28 | public static enum PlayerState { 29 | stopped, playing 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /oleaster-examples/src/test/java/com/mscharhag/oleaster/examples/OleasterIntroductionTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.examples; 2 | 3 | import org.junit.runner.RunWith; 4 | import com.mscharhag.oleaster.runner.OleasterRunner; 5 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 6 | import static com.mscharhag.oleaster.matcher.Matchers.*; 7 | 8 | /** 9 | * This test shows a minimal Oleaster test containing a suite and a spec. 10 | * It is shown in the introduction of the Oleaster documentation. 11 | * If changes in this file are made, the documentation needs be updated. 12 | */ 13 | @RunWith(OleasterRunner.class) 14 | public class OleasterIntroductionTest {{ 15 | describe("A suite", () -> { 16 | it("contains a spec with an expectation", () -> { 17 | expect(40 + 2).toEqual(42); 18 | }); 19 | }); 20 | }} 21 | -------------------------------------------------------------------------------- /oleaster-examples/src/main/java/com/mscharhag/oleaster/examples/Person.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.examples; 2 | 3 | public class Person { 4 | 5 | private String firstName; 6 | private String lastName; 7 | 8 | public Person(String firstName, String lastName) { 9 | this.firstName = firstName; 10 | this.lastName = lastName; 11 | } 12 | 13 | @Override 14 | public boolean equals(Object o) { 15 | if (this == o) return true; 16 | if (o == null || getClass() != o.getClass()) return false; 17 | 18 | Person person = (Person) o; 19 | 20 | if (!firstName.equals(person.firstName)) return false; 21 | if (!lastName.equals(person.lastName)) return false; 22 | 23 | return true; 24 | } 25 | 26 | @Override 27 | public int hashCode() { 28 | int result = firstName.hashCode(); 29 | result = 31 * result + lastName.hashCode(); 30 | return result; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /oleaster-runner/src/main/java/com/mscharhag/oleaster/runner/OleasterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.runner; 17 | 18 | import com.mscharhag.oleaster.runner.suite.SuiteBuilder; 19 | 20 | 21 | public interface OleasterTest { 22 | 23 | public void buildTestSuite(SuiteBuilder sb); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /oleaster-runner/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | com.mscharhag.oleaster 9 | oleaster 10 | 0.2.0 11 | 12 | 13 | com.mscharhag.oleaster 14 | oleaster-runner 15 | jar 16 | 0.2.0 17 | Oleaster Runner 18 | A JUnit runner to write Jasmine like JUnit tests 19 | 20 | 21 | 22 | junit 23 | junit 24 | 4.11 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /oleaster-examples/src/test/java/com/mscharhag/oleaster/examples/RunnerExamplesTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.examples; 2 | 3 | import com.mscharhag.oleaster.runner.OleasterRunner; 4 | import org.junit.runner.RunWith; 5 | 6 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 7 | 8 | @RunWith(OleasterRunner.class) 9 | public class RunnerExamplesTest {{ 10 | 11 | it("describes your test", () -> { 12 | // use assertions to check the expected result 13 | }); 14 | 15 | describe("describes your suite", () -> { 16 | // suite implementation 17 | }); 18 | 19 | describe("a suite", () -> { 20 | describe("a nested suite", () -> { 21 | // suite implementation 22 | }); 23 | }); 24 | 25 | describe("beforeEach/afterEach example", () -> { 26 | 27 | beforeEach(() -> { 28 | // runs before every spec in this suite 29 | }); 30 | 31 | afterEach(() -> { 32 | // runs after every spec in this suite 33 | }); 34 | }); 35 | }} 36 | -------------------------------------------------------------------------------- /oleaster-matcher/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | com.mscharhag.oleaster 8 | oleaster 9 | 0.2.0 10 | 11 | 12 | 4.0.0 13 | 14 | com.mscharhag.oleaster 15 | oleaster-matcher 16 | 0.2.0 17 | 18 | Oleaster Matcher 19 | jar 20 | Jasmine like matchers for Oleaster 21 | 22 | 23 | 24 | com.mscharhag.oleaster 25 | oleaster-runner 26 | 0.1.1 27 | test 28 | 29 | 30 | -------------------------------------------------------------------------------- /oleaster-runner/src/test/java/com/mscharhag/oleaster/runner/FocusedSpecTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.runner; 2 | 3 | import org.junit.runner.RunWith; 4 | 5 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 6 | import static org.junit.Assert.*; 7 | 8 | @RunWith(OleasterRunner.class) 9 | public class FocusedSpecTest {{ 10 | describe("The focused spec", () -> { 11 | 12 | fit("is focused and will run", () -> { 13 | assertTrue(true); 14 | }); 15 | 16 | it("is not focused and will not run" , () -> { 17 | fail("fail"); 18 | }); 19 | 20 | fdescribe("focused describe", () -> { 21 | it("will run", () -> { 22 | assertTrue(true); 23 | }); 24 | it("will also run", () -> { 25 | assertTrue(true); 26 | }); 27 | }); 28 | 29 | fdescribe("another focused describe", () -> { 30 | fit("is focused and will run", () -> { 31 | assertTrue(true); 32 | }); 33 | 34 | it("is not focused and will not run", () -> { 35 | fail("fail"); 36 | }); 37 | }); 38 | }); 39 | }} 40 | -------------------------------------------------------------------------------- /oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/TestUtil.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher; 2 | 3 | public class TestUtil { 4 | 5 | public static void expectAssertionError(Runnable runnable, String expectedMessage) { 6 | AssertionError assertionError = null; 7 | try { 8 | runnable.run(); 9 | } catch (AssertionError ae) { 10 | assertionError = ae; 11 | } 12 | if (assertionError == null) { 13 | throw new AssertionError("passed code block did not throw an AssertionError"); 14 | } 15 | if (expectedMessage != null) { 16 | if (!assertionError.getMessage().equals(expectedMessage)) { 17 | throw new AssertionError("Expected message '" + expectedMessage + "' but was '" + assertionError.getMessage() + "'"); 18 | } 19 | } 20 | } 21 | 22 | public static void expectAssertionError(Runnable runnable) { 23 | expectAssertionError(runnable, null); 24 | } 25 | 26 | public static Exception catchException(Runnable runnable) { 27 | Exception ex = null; 28 | try { 29 | runnable.run(); 30 | } catch (Exception e) { 31 | ex = e; 32 | } 33 | return ex; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /oleaster-runner/src/main/java/com/mscharhag/oleaster/runner/StaticSupportingSuiteBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.runner; 17 | 18 | import com.mscharhag.oleaster.runner.suite.SuiteBuilder; 19 | 20 | public class StaticSupportingSuiteBuilder extends SuiteBuilder { 21 | 22 | @Override 23 | public void beforeEvaluation() { 24 | super.beforeEvaluation(); 25 | StaticRunnerSupport.setSuiteBuilder(this); 26 | } 27 | 28 | @Override 29 | public void afterEvaluation() { 30 | super.afterEvaluation(); 31 | StaticRunnerSupport.setSuiteBuilder(null); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /oleaster-runner/src/main/java/com/mscharhag/oleaster/runner/Invokable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.runner; 17 | 18 | /** 19 | * An Invokable represents a block of code in Oleaster. 20 | * Common Oleaster functions like {@code describe()} or {@code beforeEach()} 21 | * take an Invokable as parameter. These Invokable instances are then evaluated by Oleaster 22 | * to build a set of test suites. 23 | * 24 | *

Invokable is typically implemented using a Lambda expression.

25 | * 26 | * Invokable is similar to {@code Runnable}. The only difference is that Invokable allows you to 27 | * throw checked exceptions. 28 | */ 29 | public interface Invokable { 30 | 31 | void invoke() throws Exception; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/util/Arguments.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.matcher.util; 17 | 18 | /** 19 | * Internal Utility class for validating arguments 20 | */ 21 | public class Arguments { 22 | 23 | public static void ensureNotNull(Object value, String format, Object... args) { 24 | ensureNotNull(value, String.format(format, args)); 25 | } 26 | 27 | public static void ensureNotNull(Object value, String message) { 28 | if (value == null) { 29 | throw new IllegalArgumentException(message); 30 | } 31 | } 32 | 33 | public static void ensureTrue(boolean condition, String format, Object... args) { 34 | if (!condition) { 35 | throw new IllegalArgumentException(String.format(format, args)); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/util/Expectations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.matcher.util; 17 | 18 | public class Expectations { 19 | 20 | public static void expectNotNull(Object value, String message) { 21 | if (value == null) { 22 | fail(message); 23 | } 24 | } 25 | 26 | 27 | public static void expectNotNull(Object value, String format, Object... args) { 28 | expectNotNull(value, String.format(format, args)); 29 | } 30 | 31 | 32 | public static void expectTrue(boolean condition, String message) { 33 | if (!condition) { 34 | fail(message); 35 | } 36 | } 37 | 38 | 39 | public static void expectTrue(boolean condition, String format, Object... args) { 40 | expectTrue(condition, String.format(format, args)); 41 | } 42 | 43 | 44 | public static void fail(String message) { 45 | if (message == null) { 46 | throw new AssertionError(); 47 | } 48 | throw new AssertionError(message); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /oleaster-examples/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | oleaster 8 | com.mscharhag.oleaster 9 | 0.2.0 10 | 11 | 12 | 4.0.0 13 | 14 | com.mscharhag.oleaster 15 | oleaster-examples 16 | 0.2.0 17 | 18 | 19 | 20 | com.mscharhag.oleaster 21 | oleaster-matcher 22 | 0.1.0 23 | test 24 | 25 | 26 | com.mscharhag.oleaster 27 | oleaster-runner 28 | 0.1.0 29 | test 30 | 31 | 32 | junit 33 | junit 34 | 4.11 35 | test 36 | 37 | 38 | 39 | 40 | 41 | 42 | org.apache.maven.plugins 43 | maven-deploy-plugin 44 | 2.8.2 45 | 46 | 47 | true 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/matchers/BooleanMatcherTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher.matchers; 2 | 3 | import com.mscharhag.oleaster.matcher.TestUtil; 4 | import com.mscharhag.oleaster.runner.OleasterRunner; 5 | import org.junit.runner.RunWith; 6 | 7 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 8 | 9 | @RunWith(OleasterRunner.class) 10 | public class BooleanMatcherTest { 11 | private BooleanMatcher matcher; 12 | { 13 | describe("BooleanMatcher tests", () -> { 14 | 15 | describe("when the stored value is true", () -> { 16 | beforeEach(() -> { 17 | matcher = new BooleanMatcher(true); 18 | }); 19 | 20 | it("is ok if it is checked for 'true' value",() -> { 21 | matcher.toBeTrue(); 22 | matcher.toEqual(true); 23 | }); 24 | 25 | it("fails if it is checked for 'false' value", () -> { 26 | TestUtil.expectAssertionError(matcher::toBeFalse, "Expected true to be false"); 27 | TestUtil.expectAssertionError(() -> matcher.toEqual(false), "Expected true to equal false"); 28 | }); 29 | }); 30 | 31 | describe("when the stored value is false", () -> { 32 | beforeEach(() -> { 33 | matcher = new BooleanMatcher(false); 34 | }); 35 | 36 | it("fails if it is checked for 'true' value", () -> { 37 | TestUtil.expectAssertionError(matcher::toBeTrue, "Expected false to be true"); 38 | TestUtil.expectAssertionError(() -> matcher.toEqual(true), "Expected false to equal true"); 39 | }); 40 | 41 | it("is ok if it is checked for 'false' value", () -> { 42 | matcher.toBeFalse(); 43 | matcher.toEqual(false); 44 | }); 45 | }); 46 | }); 47 | }} 48 | -------------------------------------------------------------------------------- /oleaster-examples/src/test/java/com/mscharhag/oleaster/examples/AudioPlayerExampleTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.examples; 2 | 3 | import com.mscharhag.oleaster.examples.AudioPlayer.PlayerState; 4 | import com.mscharhag.oleaster.runner.OleasterRunner; 5 | import org.junit.runner.RunWith; 6 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 7 | import static com.mscharhag.oleaster.matcher.Matchers.*; 8 | 9 | /** 10 | * This is an Oleaster example test. 11 | * These test is shown in the Oleaster Runner documentation page. 12 | * If this test is updated, the documentation should be updated too. 13 | */ 14 | @RunWith(OleasterRunner.class) 15 | public class AudioPlayerExampleTest { 16 | private AudioPlayer player; 17 | { 18 | beforeEach(() -> { 19 | // create a new AudioPlayer instance before each test 20 | player = new AudioPlayer(); 21 | }); 22 | 23 | it("sets the initial player state to stopped", () -> { 24 | expect(player.getState()).toEqual(PlayerState.stopped); 25 | }); 26 | 27 | it("sets the currently played track to null", () -> { 28 | expect(player.getCurrentlyPlayedTrack()).toBeNull(); 29 | }); 30 | 31 | describe("when a track is played", () -> { 32 | beforeEach(() -> { 33 | // play a track; this is the common precondition for all specs in this suite 34 | player.play(new Track("Run to the hills")); 35 | }); 36 | 37 | it("updates the player state to playing", () -> { 38 | expect(player.getState()).toEqual(PlayerState.playing); 39 | }); 40 | 41 | it("updates the currently played track", () -> { 42 | Track expectedTrack = new Track("Run to the hills"); 43 | expect(player.getCurrentlyPlayedTrack()).toEqual(expectedTrack); 44 | }); 45 | }); 46 | }} 47 | -------------------------------------------------------------------------------- /oleaster-runner/src/main/java/com/mscharhag/oleaster/runner/suite/SuiteDefinition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.runner.suite; 17 | 18 | import com.mscharhag.oleaster.runner.Invokable; 19 | import com.mscharhag.oleaster.runner.PendingInvokable; 20 | 21 | public class SuiteDefinition { 22 | 23 | private Suite parent; 24 | private String description; 25 | private Invokable block; 26 | private boolean parentIsPending; 27 | 28 | 29 | public SuiteDefinition(Suite parent, String description, Invokable block) { 30 | this(parent, description, block, false); 31 | } 32 | public SuiteDefinition(Suite parent, String description, Invokable block, boolean parentIsPending) { 33 | this.parent = parent; 34 | this.description = description; 35 | this.block = block; 36 | this.parentIsPending = parentIsPending; 37 | } 38 | 39 | public Suite getParent() { 40 | return parent; 41 | } 42 | 43 | public String getDescription() { 44 | return description; 45 | } 46 | 47 | public Invokable getBlock() { 48 | return block; 49 | } 50 | 51 | public boolean isPending() { 52 | return block instanceof PendingInvokable || parentIsPending; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /oleaster-runner/src/test/java/com/mscharhag/oleaster/runner/AssertUtil.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.runner; 2 | 3 | import com.mscharhag.oleaster.runner.suite.Suite; 4 | import com.mscharhag.oleaster.runner.suite.SuiteBuilder; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | import static org.junit.Assert.fail; 8 | 9 | public class AssertUtil { 10 | 11 | public static void assertEmptySuiteBuilderCollections(SuiteBuilder sb) { 12 | assertEquals(0, sb.getSuiteDefinitions().size()); 13 | assertEquals(0, sb.getAfterEachHandlers().size()); 14 | assertEquals(0, sb.getBeforeEachHandlers().size()); 15 | assertEquals(0, sb.getSpecDefinitions().size()); 16 | } 17 | 18 | 19 | public static void assertEmptySuiteCollections(Suite suite) { 20 | assertEquals(0, suite.getSpecs().size()); 21 | assertEquals(0, suite.getBeforeEachHandlers().size()); 22 | assertEquals(0, suite.getAfterEachHandlers().size()); 23 | assertEquals(0, suite.getSuites().size()); 24 | } 25 | 26 | 27 | public static ExceptionMatcher expect(Invokable block) { 28 | return new ExceptionMatcher(block); 29 | } 30 | 31 | 32 | public static class ExceptionMatcher { 33 | private Invokable block; 34 | 35 | private ExceptionMatcher(Invokable block) { 36 | this.block = block; 37 | } 38 | 39 | public void toFailWith(Class exceptionClass) { 40 | Exception ex = null; 41 | try { 42 | block.invoke(); 43 | } catch (Exception e) { 44 | ex = e; 45 | } 46 | if (ex == null) { 47 | fail("Expected exception of type " + exceptionClass.getName() + " but no exception was thrown"); 48 | } 49 | if (!ex.getClass().isAssignableFrom(exceptionClass) || !exceptionClass.isAssignableFrom(ex.getClass())) { 50 | fail("Expected exception of type " + exceptionClass.getName() + " but got " + ex.getClass().getName()); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /oleaster-runner/src/test/java/com/mscharhag/oleaster/runner/PendingSpecTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.runner; 2 | 3 | 4 | import org.junit.runner.RunWith; 5 | 6 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 7 | import static junit.framework.TestCase.*; 8 | 9 | @RunWith(OleasterRunner.class) 10 | public class PendingSpecTest {{ 11 | describe("PendingSpecs", () -> { 12 | describe("with a nested describe", () -> { 13 | it("should be executed", () -> { 14 | assertTrue(true); 15 | }); 16 | 17 | xit("should not be executed", () -> { 18 | fail("Pending it (xit) should not be executed!"); 19 | }); 20 | 21 | describe("a nested describe should be executed", () -> { 22 | it("should be fine", () -> { 23 | assertTrue(true); 24 | }); 25 | }); 26 | 27 | xdescribe("a pending describe should not be executed", () -> { 28 | it("should not be executed", () -> { 29 | fail("'it' in 'xdescribe' should not be executed!"); 30 | }); 31 | 32 | describe("a describe with a xdescribe parent", () -> { 33 | it("should not be executed", () -> { 34 | fail("'it' in 'describe' with 'xdescribe' parent should not be executed!"); 35 | }); 36 | 37 | describe("a describe with a xdescribe grandparent", () -> { 38 | it("should not be executed", () -> { 39 | fail("'it' in 'describe' with 'xdescribe' grandparent should not be executed!"); 40 | }); 41 | }); 42 | }); 43 | }); 44 | }); 45 | 46 | it("should be executed", () -> { 47 | assertTrue(true); 48 | }); 49 | 50 | xit("should not be executed", () -> { 51 | fail("Pending it (xit) should not be executed!"); 52 | }); 53 | 54 | it("another pending style of test"); 55 | }); 56 | }} 57 | -------------------------------------------------------------------------------- /oleaster-runner/src/main/java/com/mscharhag/oleaster/runner/suite/Spec.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.runner.suite; 17 | 18 | import java.util.Optional; 19 | 20 | import com.mscharhag.oleaster.runner.Invokable; 21 | 22 | import org.junit.runners.model.Statement; 23 | 24 | public class Spec extends Statement { 25 | 26 | private Suite suite; 27 | private String description; 28 | private Optional block; 29 | 30 | public Spec(Suite suite, String description, Optional block) { 31 | this.suite = suite; 32 | this.description = description; 33 | this.block = block; 34 | } 35 | 36 | public String getDescription() { 37 | return this.description; 38 | } 39 | 40 | public Suite getSuite() { 41 | return suite; 42 | } 43 | 44 | public String getFullDescription() { 45 | String suiteDescription = suite.getFullDescription(); 46 | if (suiteDescription != null) { 47 | return String.format("%s, it %s", suiteDescription, this.description); 48 | } 49 | return String.format("it %s", this.description); 50 | } 51 | 52 | @Override 53 | public void evaluate() throws Throwable { 54 | if (block.isPresent()) { 55 | block.get().invoke(); 56 | } 57 | } 58 | 59 | public Optional getBlock() { 60 | return block; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/MatchersTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher; 2 | 3 | import com.mscharhag.oleaster.runner.OleasterRunner; 4 | import org.junit.runner.RunWith; 5 | 6 | import java.util.Date; 7 | import java.util.HashMap; 8 | import java.util.LinkedList; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 13 | import static com.mscharhag.oleaster.matcher.Matchers.*; 14 | 15 | @RunWith(OleasterRunner.class) 16 | public class MatchersTest {{ 17 | 18 | // Just a few tests to make sure matchers can be accessed via expect() as intended. 19 | // More detailed tests are located in matcher specific test files 20 | 21 | describe("Matchers test", () -> { 22 | 23 | it("IntegerNumberMatcher", () -> { 24 | expect(40 + 2).toEqual(42); 25 | }); 26 | 27 | it("FloatingPointNumberMatcher", () -> { 28 | expect(39.666666 + 2.333333).toBeCloseTo(42.0); 29 | }); 30 | 31 | it("ExceptionMatcher", () -> { 32 | expect(() -> { 33 | throw new NullPointerException("test"); 34 | }).toThrow(NullPointerException.class); 35 | }); 36 | 37 | it("BooleanMatcher", () -> { 38 | expect(true).toBeTrue(); 39 | }); 40 | 41 | it("StringMatcher", () -> { 42 | expect("foo").toEndWith("oo"); 43 | }); 44 | 45 | it("Date", () -> { 46 | Long millis = System.currentTimeMillis(); 47 | Integer delta = 5; 48 | Date date = new Date(millis); 49 | Date dateWithinDelta = new Date(millis+delta-1); 50 | expect(date).toBeCloseTo(dateWithinDelta, delta); 51 | }); 52 | 53 | it("CollectionMatcher", () -> { 54 | final List list = new LinkedList<>(); 55 | list.add("one"); 56 | list.add("two"); 57 | expect(list).toContain("one"); 58 | }); 59 | 60 | it("MapMatcher", () -> { 61 | final Map map = new HashMap<>(); 62 | map.put("one", false); 63 | map.put("two", true); 64 | expect(map).toContainKey("one"); 65 | expect(map).toContainValue(true); 66 | }); 67 | }); 68 | }} 69 | -------------------------------------------------------------------------------- /oleaster-runner/src/test/java/com/mscharhag/oleaster/runner/SpecTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.runner; 2 | 3 | import java.util.Optional; 4 | 5 | import com.mscharhag.oleaster.runner.suite.Spec; 6 | import com.mscharhag.oleaster.runner.suite.Suite; 7 | 8 | import org.junit.runner.RunWith; 9 | 10 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 11 | import static org.junit.Assert.*; 12 | 13 | @RunWith(OleasterRunner.class) 14 | public class SpecTest { 15 | 16 | private Suite suite; 17 | private Spec spec; 18 | private Optional emptyInvokable = Optional.of(() -> {}); 19 | 20 | { 21 | describe("Spec", () -> { 22 | 23 | beforeEach(() -> { 24 | suite = new Suite(null, "suite"); 25 | }); 26 | 27 | describe("when a simple spec is created", () -> { 28 | beforeEach(() -> { 29 | spec = new Spec(suite, "test spec", emptyInvokable); 30 | }); 31 | 32 | it("returns the suite", () -> { 33 | assertEquals(suite, spec.getSuite()); 34 | }); 35 | 36 | it("returns the description", () -> { 37 | assertEquals("test spec", spec.getDescription()); 38 | }); 39 | 40 | it("returns the suite description followed by the spec description as full description", () -> { 41 | assertEquals("suite, it test spec", spec.getFullDescription()); 42 | }); 43 | }); 44 | 45 | describe("when the suite has a parent suite", () -> { 46 | beforeEach(() -> { 47 | Suite childSuite = new Suite(suite, "child suite"); 48 | spec = new Spec(childSuite, "test spec", emptyInvokable); 49 | }); 50 | 51 | it("returns the description of all parent suites followed by the spec description as full description", () -> { 52 | assertEquals("suite, child suite, it test spec", spec.getFullDescription()); 53 | }); 54 | }); 55 | 56 | describe("when the suite does not return a description", () -> { 57 | beforeEach(() -> { 58 | suite = new Suite(null, null); 59 | spec = new Spec(suite, "test spec", emptyInvokable); 60 | }); 61 | 62 | it("returns only the spec description as full description", () -> { 63 | assertEquals("it test spec", spec.getFullDescription()); 64 | }); 65 | }); 66 | }); 67 | 68 | }} 69 | -------------------------------------------------------------------------------- /oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/BooleanMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.matcher.matchers; 17 | 18 | import com.mscharhag.oleaster.matcher.util.Expectations; 19 | 20 | /** 21 | * Matcher class to validate boolean values 22 | */ 23 | public class BooleanMatcher { 24 | 25 | private boolean value; 26 | 27 | /** 28 | * Creates a new BooleanMatcher that can be used to validate the passed {@code value}. 29 | * @param value the value that should be validated 30 | */ 31 | public BooleanMatcher(boolean value) { 32 | this.value = value; 33 | } 34 | 35 | /** 36 | * Checks if the stored value is equal to another value. 37 | *

This method throws an {@code AssertionError} if the stored value is not equal to {@code other}. 38 | * @param other the value to compare with 39 | */ 40 | public void toEqual(boolean other) { 41 | Expectations.expectTrue(this.value == other, "Expected %s to equal %s", this.value, other); 42 | } 43 | 44 | /** 45 | * Checks if the stored value is {@code true}. 46 | *

This method throws an {@code AssertionError} if the stored value is {@code false}. 47 | */ 48 | public void toBeTrue() { 49 | Expectations.expectTrue(this.value, "Expected %s to be true", this.value); 50 | } 51 | 52 | /** 53 | * Checks if the stored value is {@code false}. 54 | *

This method throws an {@code AssertionError} if the stored value is {@code true}. 55 | */ 56 | public void toBeFalse() { 57 | Expectations.expectTrue(!this.value, "Expected %s to be false", this.value); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/matchers/ExceptionMatcherTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher.matchers; 2 | 3 | import com.mscharhag.oleaster.matcher.TestUtil; 4 | import com.mscharhag.oleaster.runner.OleasterRunner; 5 | import org.junit.runner.RunWith; 6 | 7 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 8 | 9 | @RunWith(OleasterRunner.class) 10 | public class ExceptionMatcherTest { 11 | private ExceptionMatcher matcher; 12 | { 13 | describe("ExceptionMatcher tests", () -> { 14 | 15 | describe("when the passed code block throws an exception", () -> { 16 | beforeEach(() -> { 17 | matcher = new ExceptionMatcher(() -> { 18 | throw new IllegalArgumentException("test exception"); 19 | }); 20 | }); 21 | 22 | it("fails if it is checked for a different exception class", () -> { 23 | TestUtil.expectAssertionError(() -> matcher.toThrow(NullPointerException.class)); 24 | }); 25 | 26 | it("is ok if it is checked for the correct exception class", () -> { 27 | matcher.toThrow(IllegalArgumentException.class); 28 | }); 29 | 30 | it("is ok if it is checked with the correct exception class and the correct message", () -> { 31 | matcher.toThrow(IllegalArgumentException.class, "test exception"); 32 | }); 33 | 34 | it("fails if the exception message is not equal to the expected message", () -> { 35 | String expectedMessage = "Expected exception message 'foo' but was 'test exception'"; 36 | TestUtil.expectAssertionError(() -> matcher.toThrow(IllegalArgumentException.class, "foo"), expectedMessage); 37 | }); 38 | 39 | it("is ok if it is checked for a super class of the thrown exception", () -> { 40 | matcher.toThrow(RuntimeException.class); 41 | }); 42 | }); 43 | 44 | describe("when the passed code block throws no exception", () -> { 45 | beforeEach(() -> { 46 | matcher = new ExceptionMatcher(() -> {}); 47 | }); 48 | 49 | it("fails if it is checked for an exception", () -> { 50 | TestUtil.expectAssertionError(() -> matcher.toThrow(IllegalArgumentException.class)); 51 | }); 52 | 53 | it("fails if it is checked for an exception and a message", () -> { 54 | TestUtil.expectAssertionError(() -> matcher.toThrow(IllegalArgumentException.class, "foo")); 55 | }); 56 | }); 57 | 58 | }); 59 | }} 60 | -------------------------------------------------------------------------------- /oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/ObjectMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.matcher.matchers; 17 | 18 | 19 | import static com.mscharhag.oleaster.matcher.util.Expectations.*; 20 | 21 | /** 22 | * Matcher class to validate Objects of type {@code T}. 23 | */ 24 | public class ObjectMatcher { 25 | 26 | private T value; 27 | 28 | public ObjectMatcher(T value) { 29 | this.value = value; 30 | } 31 | 32 | /** 33 | * Checks if the stored value is equal to {@code other}. 34 | *

This method throws an {@code AssertionError} if the stored value is not equal to {@code other}. 35 | * @param other the value to compare with 36 | */ 37 | public void toEqual(T other) { 38 | if (this.value == null && other == null) { 39 | return; 40 | } 41 | expectNotNull(this.value, "Expected null to be equal '%s'", other); 42 | expectNotNull(other, "Expected '%s' to be equal null", this.value); 43 | expectTrue(this.value.equals(other), "Expected '%s' to be equal '%s'", this.value, other); 44 | } 45 | 46 | /** 47 | * Checks if the stored value is {@code null}. 48 | *

This method throws an {@code AssertionError} if the stored value is {@code null}. 49 | */ 50 | public void toBeNull() { 51 | expectTrue(this.value == null, "Expected '%s' to be null", this.value); 52 | } 53 | 54 | /** 55 | * Checks if the stored value is not {@code null}. 56 | *

This method throws an {@code AssertionError} if the stored value is not {@code null}. 57 | */ 58 | public void toBeNotNull() { 59 | expectTrue(this.value != null, "Expected null to be not null"); 60 | } 61 | 62 | /** 63 | * Checks if the stored value is an instance of the {@code expectedClass} 64 | *

This method throws an {@code AssertionError} if the stored value is not of instance of {@code expectedClass}. 65 | * @param expectedClass The expected class 66 | */ 67 | public void toBeInstanceOf(Class expectedClass) { 68 | expectTrue(expectedClass.isInstance(value), "Expected '%s' to be instance of '%s'", this.value, expectedClass.getName()); 69 | } 70 | 71 | protected T getValue() { 72 | return this.value; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /oleaster-runner/src/test/java/com/mscharhag/oleaster/runner/OleasterRunnerTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.runner; 2 | 3 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 4 | 5 | import com.mscharhag.oleaster.runner.suite.Spec; 6 | import com.mscharhag.oleaster.runner.suite.Suite; 7 | import com.mscharhag.oleaster.runner.suite.SuiteBuilder; 8 | import org.junit.runner.RunWith; 9 | import org.junit.runner.notification.RunNotifier; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | import java.util.*; 14 | import java.util.function.Function; 15 | import java.util.stream.Collectors; 16 | 17 | @RunWith(OleasterRunner.class) 18 | public class OleasterRunnerTest { 19 | 20 | private static List calls; 21 | private static Function block = (String name) -> () -> { calls.add(name); }; 22 | 23 | private OleasterRunner runner; 24 | private Suite suite; 25 | private List specs; 26 | 27 | public static class TestClass {{ 28 | describe("outer describe", () -> { 29 | describe("inner describe", () -> { 30 | it("inner it", block.apply("inner it")); 31 | }); 32 | it("outer it", block.apply("outer it")); 33 | }); 34 | }} 35 | 36 | 37 | public static class OleasterTestImplementingTestClass implements OleasterTest { 38 | 39 | public static SuiteBuilder suiteBuilder; 40 | 41 | @Override 42 | public void buildTestSuite(SuiteBuilder sb) { 43 | suiteBuilder = sb; 44 | } 45 | } 46 | 47 | { 48 | describe("OleasterRunner", () -> { 49 | 50 | beforeEach(() -> { 51 | calls = new ArrayList<>(); 52 | runner = new OleasterRunner(TestClass.class); 53 | }); 54 | 55 | it("adds the filtered children to the suite", () -> { 56 | int numberOfChildren = runner.getDescription().getChildren().size(); 57 | assertEquals(2, numberOfChildren); 58 | }); 59 | 60 | describe("when specs are obtained from the test class using getChildren()", () -> { 61 | 62 | beforeEach(() -> { 63 | specs = runner.getChildren(); 64 | }); 65 | 66 | it("returns a list that contains all specs", () -> { 67 | List specNames = specs.stream().map(Spec::getDescription).collect(Collectors.toList()); 68 | assertEquals(Arrays.asList("outer it", "inner it"), specNames); 69 | }); 70 | 71 | describe("when the test class implements OleasterTest", () -> { 72 | beforeEach(() -> { 73 | OleasterTestImplementingTestClass.suiteBuilder = null; 74 | runner = new OleasterRunner(OleasterTestImplementingTestClass.class); 75 | runner.getChildren(); 76 | }); 77 | 78 | it("calls buildTestSuite() and passes a SuiteBuilder instance", () -> { 79 | assertNotNull(OleasterTestImplementingTestClass.suiteBuilder); 80 | }); 81 | }); 82 | }); 83 | }); 84 | 85 | }} 86 | -------------------------------------------------------------------------------- /oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/matchers/StringMatcherTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher.matchers; 2 | 3 | import static com.mscharhag.oleaster.matcher.TestUtil.*; 4 | import com.mscharhag.oleaster.runner.OleasterRunner; 5 | import org.junit.runner.RunWith; 6 | 7 | import java.util.regex.Pattern; 8 | 9 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 10 | 11 | @RunWith(OleasterRunner.class) 12 | public class StringMatcherTest {{ 13 | describe("StringMatcher test", () -> { 14 | 15 | describe("when toMatch() is called", () -> { 16 | it("fails if the stored value does not match the expected pattern", () -> { 17 | expectAssertionError(() -> new StringMatcher("foo").toMatch(Pattern.compile("bar")), 18 | "Expected 'foo' to match 'bar'"); 19 | }); 20 | 21 | it("fails if the stored value is null", () -> { 22 | expectAssertionError(() -> new StringMatcher(null).toMatch(Pattern.compile("bar")), 23 | "Expected null to match 'bar'"); 24 | }); 25 | 26 | it("is ok if the stored value matches the expected pattern", () -> { 27 | new StringMatcher("foo").toMatch(Pattern.compile("fo{2}")); 28 | }); 29 | 30 | it("creates a pattern instance if the pattern is passed as string", () -> { 31 | new StringMatcher("foo").toMatch("fo{2}"); 32 | }); 33 | }); 34 | 35 | 36 | describe("when toStartWith() is called", () -> { 37 | it("fails if the stored value is null", () -> { 38 | expectAssertionError(() -> new StringMatcher(null).toStartWith("bar"), "Expected null to start with 'bar'"); 39 | }); 40 | 41 | it("fails if the stored value does not start with the expected sub string", () -> { 42 | expectAssertionError(() -> new StringMatcher("foo").toStartWith("fee"), "Expected 'foo' to start with 'fee'"); 43 | }); 44 | 45 | it("is ok if the stored value starts with the expected sub string", () -> { 46 | new StringMatcher("foo").toStartWith("fo"); 47 | }); 48 | }); 49 | 50 | 51 | describe("when toEndWith() is called", () -> { 52 | it("fails if the stored value is null", () -> { 53 | expectAssertionError(() -> new StringMatcher(null).toEndWith("bar"), "Expected null to end with 'bar'"); 54 | }); 55 | 56 | it("fails if the stored value does not end with the expected sub string", () -> { 57 | expectAssertionError(() -> new StringMatcher("foo").toEndWith("fee"), "Expected 'foo' to end with 'fee'"); 58 | }); 59 | 60 | it("is ok if the stored value ends with the expected sub string", () -> { 61 | new StringMatcher("foo").toEndWith("oo"); 62 | }); 63 | }); 64 | 65 | 66 | describe("when toContain() is called", () -> { 67 | it("fails if the stored value is null", () -> { 68 | expectAssertionError(() -> new StringMatcher(null).toContain("bar"), "Expected null to contain 'bar'"); 69 | }); 70 | 71 | it("fails if the stored value does not contain the passed value", () -> { 72 | expectAssertionError(() -> new StringMatcher("foo").toContain("a"), "Expected 'foo' to contain 'a'"); 73 | }); 74 | 75 | it("is ok if the stored value contains the passed value", () -> { 76 | new StringMatcher("foo").toContain("o"); 77 | }); 78 | }); 79 | }); 80 | }} 81 | -------------------------------------------------------------------------------- /oleaster-runner/src/main/java/com/mscharhag/oleaster/runner/suite/SuiteDefinitionEvaluator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.runner.suite; 17 | 18 | import java.util.Map; 19 | import java.util.Optional; 20 | 21 | import com.mscharhag.oleaster.runner.Invokable; 22 | 23 | public class SuiteDefinitionEvaluator { 24 | 25 | 26 | public Suite evaluate(SuiteDefinition suiteDefinition, SuiteBuilder suiteBuilder) { 27 | this.invokeSuiteDefinition(suiteDefinition, suiteBuilder); 28 | return this.createSuite(suiteDefinition, suiteBuilder); 29 | } 30 | 31 | 32 | private void invokeSuiteDefinition(SuiteDefinition suiteDefinition, SuiteBuilder suiteBuilder) { 33 | suiteBuilder.beforeEvaluation(); 34 | try { 35 | suiteDefinition.getBlock().invoke(); 36 | } catch (Exception e) { 37 | String message = String.format("An error occurred while evaluating suite '%s'", suiteDefinition.getDescription()); 38 | throw new RuntimeException(message, e); 39 | } finally { 40 | suiteBuilder.afterEvaluation(); 41 | } 42 | } 43 | 44 | 45 | private Suite createSuite(SuiteDefinition suiteDefinition, SuiteBuilder suiteBuilder) { 46 | Suite suite = new Suite(suiteDefinition.getParent(), suiteDefinition.getDescription()); 47 | 48 | suite.addBeforeHandlers(suiteBuilder.getBeforeHandlers()); 49 | suite.addBeforeEachHandlers(suiteBuilder.getBeforeEachHandlers()); 50 | suite.addAfterEachHandlers(suiteBuilder.getAfterEachHandlers()); 51 | suite.addAfterHandlers(suiteBuilder.getAfterHandlers()); 52 | 53 | Map> specDefinitions = suiteBuilder.getFocusedSpecDefinitions().size() > 0 54 | ? suiteBuilder.getFocusedSpecDefinitions() 55 | : suiteBuilder.getSpecDefinitions(); 56 | 57 | specDefinitions.forEach((description, block) -> 58 | suite.addSpec(new Spec(suite, description, suiteDefinition.isPending() ? Optional.empty() : block))); 59 | 60 | if (suiteBuilder.getFocusedSuiteDefinitions().size() > 0) { 61 | suiteBuilder.getFocusedSuiteDefinitions().forEach((description, block) -> { 62 | SuiteDefinition childSuiteDefinition = new SuiteDefinition(suite, description, block, suiteDefinition.isPending()); 63 | suite.addChildSuite(this.evaluate(childSuiteDefinition, suiteBuilder)); 64 | }); 65 | } else { 66 | suiteBuilder.getSuiteDefinitions().forEach((description, block) -> { 67 | SuiteDefinition childSuiteDefinition = new SuiteDefinition(suite, description, block, suiteDefinition.isPending()); 68 | suite.addChildSuite(this.evaluate(childSuiteDefinition, suiteBuilder)); 69 | }); 70 | } 71 | 72 | return suite; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | org.sonatype.oss 9 | oss-parent 10 | 7 11 | 12 | 13 | com.mscharhag.oleaster 14 | oleaster 15 | pom 16 | 0.2.0 17 | Oleaster 18 | 19 | 20 | oleaster-runner 21 | oleaster-matcher 22 | oleaster-examples 23 | 24 | 25 | https://github.com/mscharhag/oleaster 26 | 27 | 28 | https://github.com/mscharhag/oleaster 29 | scm:git:git://github.com/mscharhag/oleaster.git 30 | 31 | 32 | 33 | 34 | The Apache Software License, Version 2.0 35 | http://www.apache.org/licenses/LICENSE-2.0.txt 36 | 37 | 38 | 39 | 40 | 41 | mscharhag 42 | Michael Scharhag 43 | 44 | 45 | 46 | 47 | 48 | release-sign-artifacts 49 | 50 | 51 | performRelease 52 | true 53 | 54 | 55 | 56 | 57 | 58 | org.apache.maven.plugins 59 | maven-gpg-plugin 60 | 61 | 62 | ${gpg.key} 63 | 64 | 65 | 66 | sign-artifacts 67 | verify 68 | 69 | sign 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | org.apache.maven.plugins 83 | maven-compiler-plugin 84 | 3.1 85 | 86 | 1.8 87 | 1.8 88 | 89 | 90 | 91 | org.apache.maven.plugins 92 | maven-source-plugin 93 | 94 | 95 | attach-sources 96 | 97 | jar 98 | 99 | 100 | 101 | 102 | 103 | org.apache.maven.plugins 104 | maven-javadoc-plugin 105 | 106 | 107 | attach-javadocs 108 | 109 | jar 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/datetime/DateMatcher.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher.matchers.datetime; 2 | 3 | import com.mscharhag.oleaster.matcher.matchers.ObjectMatcher; 4 | import com.mscharhag.oleaster.matcher.util.Arguments; 5 | 6 | import java.text.SimpleDateFormat; 7 | import java.util.Date; 8 | 9 | import static com.mscharhag.oleaster.matcher.util.Expectations.expectNotNull; 10 | import static com.mscharhag.oleaster.matcher.util.Expectations.expectTrue; 11 | 12 | public class DateMatcher extends ObjectMatcher { 13 | 14 | protected static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 15 | 16 | 17 | public DateMatcher(Date date) { 18 | super(date); 19 | } 20 | 21 | private String formatDate(Date date) { 22 | return dateFormat.format(date); 23 | } 24 | 25 | 26 | public void toBeBefore(Date otherDate) { 27 | Arguments.ensureNotNull(otherDate, "Cannot test if a date is before null, otherDate cannot be null"); 28 | expectNotNull(this.getValue(), "Expected null to be before '%s'", this.formatDate(otherDate)); 29 | expectTrue(this.getValue().before(otherDate), "Expected '%s' to be before '%s'", 30 | this.formatDate(this.getValue()), this.formatDate(otherDate)); 31 | } 32 | 33 | 34 | public void toBeAfter(Date otherDate) { 35 | Arguments.ensureNotNull(otherDate, "Cannot test if a date is after null, otherDate cannot be null"); 36 | expectNotNull(this.getValue(), "Expected null to be after '%s'", this.formatDate(otherDate)); 37 | expectTrue(this.getValue().after(otherDate), "Expected '%s' to be after '%s'", 38 | this.formatDate(this.getValue()), this.formatDate(otherDate)); 39 | } 40 | 41 | 42 | public void toBeBetween(Date first, Date second) { 43 | Arguments.ensureNotNull(first, "first cannot be null"); 44 | Arguments.ensureNotNull(second, "second cannot be null"); 45 | Arguments.ensureTrue(first.before(second), "first date needs to be before second date"); 46 | expectNotNull(this.getValue(), "Expected null to be between '%s' and '%s'", 47 | this.formatDate(first), this.formatDate(second)); 48 | expectTrue((this.getValue().equals(first) || this.getValue().after(first)) && this.getValue().before(second), 49 | "Expected '%s' to be between '%s' and '%s'", this.formatDate(this.getValue()), this.formatDate(first), this.formatDate(second)); 50 | } 51 | 52 | 53 | public void toBeCloseTo(Date otherDate, long deltaMillis) { 54 | Arguments.ensureNotNull(otherDate, "otherDate cannot be null"); 55 | Arguments.ensureTrue(deltaMillis > 0, "deltaMillis need to be greater than zero"); 56 | expectNotNull(this.getValue(), "Expected null to be close to '%s', delta: %sms", 57 | this.formatDate(otherDate), deltaMillis); 58 | 59 | long millis = otherDate.getTime(); 60 | Date min = new Date(millis - deltaMillis); 61 | Date max = new Date(millis + deltaMillis); 62 | 63 | expectTrue(this.getValue().after(min) && this.getValue().before(max), 64 | "Expected '%s' to be close to '%s', delta: %sms", this.formatDate(this.getValue()), 65 | this.formatDate(otherDate), deltaMillis); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Oleaster 2 | ===== 3 | 4 | Oleaster allows you to write JUnit tests like you would write [Jasmine](http://jasmine.github.io/) tests. 5 | 6 | An Oleaster JUnit test looks like this: 7 | 8 | ```java 9 | @RunWith(OleasterRunner.class) 10 | public class OleasterIntroductionTest {{ 11 | describe("A suite", () -> { 12 | it("contains a spec with an expectation", () -> { 13 | expect(40 + 2).toEqual(42); 14 | }); 15 | }); 16 | }} 17 | ``` 18 | 19 | Oleaster consists out of two independent libraries: 20 | 21 | The [Oleaster JUnit Runner](https://github.com/mscharhag/oleaster/tree/master/oleaster-runner) gives you the option 22 | to write JUnit tests in the format shown above. Java 8 Lambda expressions are used to structure a test in suites 23 | and specifications. 24 | 25 | [Oleaster-Matcher](https://github.com/mscharhag/oleaster/tree/master/oleaster-matcher) 26 | provides Jasmine-like Matchers (`expect(..).toEqual(..)`) to validate test results. These Matchers can be used 27 | as a replacement (or extension) for standard JUnit assertions. 28 | 29 | ## Documentation and examples 30 | 31 | [Oleaster JUnit Runner Documentation](https://github.com/mscharhag/oleaster/blob/master/oleaster-runner/README.md) 32 | 33 | [Oleaster Matcher Documentation](https://github.com/mscharhag/oleaster/blob/master/oleaster-matcher/README.md) 34 | 35 | [Source of the AudioPlayer example](https://github.com/mscharhag/oleaster/blob/master/oleaster-examples/src/test/java/com/mscharhag/oleaster/examples/AudioPlayerExampleTest.java) from the Oleaster Runner documentation. 36 | 37 | Oleaster tests are (mostly) written with Oleaster (see: [Oleaster JUnit Runner Tests](https://github.com/mscharhag/oleaster/tree/master/oleaster-runner/src/test/java/com/mscharhag/oleaster/runner) and [Oleaster Matcher Tests](https://github.com/mscharhag/oleaster/tree/master/oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/matchers)). 38 | 39 | Travis CI builds can be found [here](https://travis-ci.org/mscharhag/oleaster) 40 | 41 | ## Maven dependencies 42 | ```xml 43 | 44 | 45 | 46 | 47 | com.mscharhag.oleaster 48 | oleaster-matcher 49 | 0.2.0 50 | 51 | 52 | 53 | 54 | com.mscharhag.oleaster 55 | oleaster-runner 56 | 0.2.0 57 | 58 | 59 | 60 | 61 | junit 62 | junit 63 | 4.11 64 | 65 | 66 | 67 | ``` 68 | 69 | ## License 70 | 71 | This software is licensed under the Apache 2 license, quoted below. 72 | 73 | Copyright 2017 Michael Scharhag 74 | 75 | Licensed under the Apache License, Version 2.0 (the "License"); 76 | you may not use this file except in compliance with the License. 77 | You may obtain a copy of the License at 78 | 79 | http://www.apache.org/licenses/LICENSE-2.0 80 | 81 | Unless required by applicable law or agreed to in writing, software 82 | distributed under the License is distributed on an "AS IS" BASIS, 83 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 84 | See the License for the specific language governing permissions and 85 | limitations under the License. 86 | -------------------------------------------------------------------------------- /oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/matchers/ObjectMatcherTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher.matchers; 2 | 3 | import com.mscharhag.oleaster.runner.OleasterRunner; 4 | 5 | import org.junit.runner.RunWith; 6 | 7 | import static com.mscharhag.oleaster.matcher.TestUtil.*; 8 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 9 | 10 | @RunWith(OleasterRunner.class) 11 | public class ObjectMatcherTest {{ 12 | describe("ObjectMatcher tests", () -> { 13 | describe("when toEqual() is called", () -> { 14 | it("fails if both values are not equal", () -> { 15 | expectAssertionError(() -> new ObjectMatcher<>("foo").toEqual("bar"), 16 | "Expected 'foo' to be equal 'bar'"); 17 | }); 18 | 19 | it("fails if the matcher value is null", () -> { 20 | expectAssertionError(() -> new ObjectMatcher(null).toEqual("bar"), 21 | "Expected null to be equal 'bar'"); 22 | }); 23 | 24 | it("fails if the passed value is null", () -> { 25 | expectAssertionError(() -> new ObjectMatcher<>("foo").toEqual(null), 26 | "Expected 'foo' to be equal null"); 27 | }); 28 | 29 | it("is ok if both values are equal", () -> { 30 | new ObjectMatcher<>("foo").toEqual("foo"); 31 | }); 32 | 33 | it("is ok if the stored value and the expected value are null", () -> { 34 | new ObjectMatcher<>(null).toEqual(null); 35 | }); 36 | }); 37 | 38 | describe("when toBeNull() is called", () -> { 39 | it("fails if the value is not null", () -> { 40 | expectAssertionError(() -> new ObjectMatcher<>("foo").toBeNull(), "Expected 'foo' to be null"); 41 | }); 42 | 43 | it("is ok if the value is null", () -> { 44 | new ObjectMatcher<>(null).toBeNull(); 45 | }); 46 | }); 47 | 48 | describe("when toBeNotNull() is called", () -> { 49 | it("fails if the value is null", () -> { 50 | expectAssertionError(() -> new ObjectMatcher<>(null).toBeNotNull(), "Expected null to be not null"); 51 | }); 52 | 53 | it("is ok if the value is not null", () -> { 54 | new ObjectMatcher<>("foo").toBeNotNull(); 55 | }); 56 | }); 57 | 58 | describe("when toBeInstanceOf() is called", () -> { 59 | it("fails if the value is not of instance of input", () -> { 60 | expectAssertionError(() -> new ObjectMatcher<>("foo").toBeInstanceOf(Integer.class), "Expected 'foo' to be instance of 'java.lang.Integer'"); 61 | }); 62 | 63 | it("is ok if the value is instance of the expected class", () -> { 64 | new ObjectMatcher<>("foo").toBeInstanceOf(String.class); 65 | 66 | }); 67 | 68 | it("is ok if the value is of the same class", () -> { 69 | final Animal john = new Animal("John"); 70 | new ObjectMatcher<>(john).toBeInstanceOf(Animal.class); 71 | }); 72 | 73 | it("is ok if the value is a child of the parent class", () -> { 74 | final Dog marie = new Dog("Marie"); 75 | new ObjectMatcher<>(marie).toBeInstanceOf(Animal.class); 76 | }); 77 | 78 | it("is not ok if the value is a parent of the child class", () -> { 79 | final Animal bo = new Animal("Bo"); 80 | expectAssertionError(() -> new ObjectMatcher<>(bo).toBeInstanceOf(Dog.class), "Expected '" + bo + "' to be instance of '" + Dog.class.getName() + "'"); 81 | }); 82 | 83 | }); 84 | }); 85 | } 86 | public static class Animal { 87 | public final String name; 88 | public Animal(final String name) { 89 | this.name = name; 90 | } 91 | } 92 | public static class Dog extends Animal { 93 | public Dog(final String name) { 94 | super(name); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/IntegerNumberMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.matcher.matchers; 17 | 18 | import com.mscharhag.oleaster.matcher.util.Arguments; 19 | import com.mscharhag.oleaster.matcher.util.Expectations; 20 | 21 | /** 22 | * Matcher class to validate integer numbers 23 | */ 24 | public class IntegerNumberMatcher { 25 | 26 | private long value; 27 | 28 | /** 29 | * Creates a new matcher object that stores the passed value. 30 | * @param value the value to store 31 | */ 32 | public IntegerNumberMatcher(long value) { 33 | this.value = value; 34 | } 35 | 36 | /** 37 | * Checks if the stored value is equal to another value. 38 | *

This method throws an {@code AssertionError} if the stored value is not equal to {@code other}. 39 | * 40 | * @param other the value to compare with 41 | */ 42 | public void toEqual(long other) { 43 | Expectations.expectTrue(this.value == other, "Expected %s to equal %s", this.value, other); 44 | } 45 | 46 | /** 47 | * Checks if the stored value is greater than another value. 48 | *

This method throws an {@code AssertionError} if: 49 | *

    50 | *
  • the stored value is smaller than {@code other}
  • 51 | *
  • the stored value is equal to {@code other}
  • 52 | *
53 | * @param other the value to compare with 54 | */ 55 | public void toBeGreaterThan(long other) { 56 | Expectations.expectTrue(this.value > other, "Expected %s to be greater than %s", this.value, other); 57 | } 58 | 59 | /** 60 | * Checks if the stored value is smaller than another value. 61 | *

This method throws an {@code AssertionError} if: 62 | *

    63 | *
  • the stored value is greater than {@code other}
  • 64 | *
  • the stored value is equal to {@code other}
  • 65 | *
66 | * @param other the value to compare with 67 | */ 68 | public void toBeSmallerThan(long other) { 69 | Expectations.expectTrue(this.value < other, "Expected %s to be smaller than %s", this.value, other); 70 | } 71 | 72 | /** 73 | * Checks if the stored value is between a lower and an upper bound. 74 | *

This method throws an {@code AssertionError} if: 75 | *

    76 | *
  • the stored value is smaller than the lower bound
  • 77 | *
  • the stored value is greater than the upper bound
  • 78 | *
79 | *

It is ok if the stored value is equal to the lower or the upper bound. 80 | * @param lower the lower bound 81 | * @param upper the upper bound 82 | * @throws java.lang.IllegalArgumentException if {@code lower} is not smaller than {@code upper} 83 | */ 84 | public void toBeBetween(long lower, long upper) { 85 | Arguments.ensureTrue(lower < upper, "upper has to be greater than lower"); 86 | boolean isBetween = this.value >= lower && this.value <= upper; 87 | Expectations.expectTrue(isBetween, "Expected %s to be between %s and %s", this.value, lower, upper); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/matchers/IntegerNumberMatcherTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher.matchers; 2 | 3 | import com.mscharhag.oleaster.matcher.TestUtil; 4 | import com.mscharhag.oleaster.matcher.matchers.IntegerNumberMatcher; 5 | import com.mscharhag.oleaster.runner.OleasterRunner; 6 | import static org.junit.Assert.*; 7 | import org.junit.runner.RunWith; 8 | 9 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 10 | 11 | @RunWith(OleasterRunner.class) 12 | public class IntegerNumberMatcherTest {{ 13 | describe("IntegerNumberMatcher tests", () -> { 14 | 15 | describe("when toEqual() is called", () -> { 16 | it("fails if both values are not equal", () -> { 17 | TestUtil.expectAssertionError(() -> new IntegerNumberMatcher(1).toEqual(2), "Expected 1 to equal 2"); 18 | }); 19 | 20 | it("is ok if both values are equal", () -> { 21 | new IntegerNumberMatcher(1).toEqual(1); 22 | }); 23 | }); 24 | 25 | describe("when toBeGreaterThan() is called", () -> { 26 | it("fails if the passed value greater", () -> { 27 | TestUtil.expectAssertionError(() -> new IntegerNumberMatcher(1).toBeGreaterThan(2), 28 | "Expected 1 to be greater than 2"); 29 | }); 30 | 31 | it("fails if both values are equal", () -> { 32 | TestUtil.expectAssertionError(() -> new IntegerNumberMatcher(1).toBeGreaterThan(1), 33 | "Expected 1 to be greater than 1"); 34 | }); 35 | 36 | it("is ok if the passed value is smaller", () -> { 37 | new IntegerNumberMatcher(1).toBeGreaterThan(0); 38 | }); 39 | }); 40 | 41 | describe("when toBeSmallerThan() is called", () -> { 42 | it("fails if the passed value smaller", () -> { 43 | TestUtil.expectAssertionError(() -> new IntegerNumberMatcher(1).toBeSmallerThan(0), 44 | "Expected 1 to be smaller than 0"); 45 | }); 46 | 47 | it("fails if both values are equal", () -> { 48 | TestUtil.expectAssertionError(() -> new IntegerNumberMatcher(1).toBeSmallerThan(1), 49 | "Expected 1 to be smaller than 1"); 50 | }); 51 | 52 | it("is ok if the passed value is greater", () -> { 53 | new IntegerNumberMatcher(1).toBeSmallerThan(2); 54 | }); 55 | }); 56 | 57 | describe("when toBeBetween() is called", () -> { 58 | it("throws an exception if the lower bound is greater than the upper bound", () -> { 59 | Exception ex = TestUtil.catchException(() -> new IntegerNumberMatcher(1).toBeBetween(2, 1)); 60 | assertTrue(ex instanceof IllegalArgumentException); 61 | }); 62 | 63 | it("throws an exception if the lower bound is equal to the upper bound", () -> { 64 | Exception ex = TestUtil.catchException(() -> new IntegerNumberMatcher(1).toBeBetween(2, 2)); 65 | assertTrue(ex instanceof IllegalArgumentException); 66 | }); 67 | 68 | it("fails if the value smaller than the lower bound", () -> { 69 | TestUtil.expectAssertionError(() -> new IntegerNumberMatcher(1).toBeBetween(2, 3), 70 | "Expected 1 to be between 2 and 3"); 71 | }); 72 | 73 | it("is ok if the value is equal to the lower bound", () -> { 74 | new IntegerNumberMatcher(1).toBeBetween(1, 2); 75 | }); 76 | 77 | it("is ok if the value is greater than the lower bound and lower than the upper bound", () -> { 78 | new IntegerNumberMatcher(1).toBeBetween(0, 2); 79 | }); 80 | 81 | it("is ok if the value is equal to the upper bound", () -> { 82 | new IntegerNumberMatcher(1).toBeBetween(0, 1); 83 | }); 84 | 85 | it("fails if the value is greater than the upper bound", () -> { 86 | TestUtil.expectAssertionError(() -> new IntegerNumberMatcher(2).toBeBetween(0, 1), 87 | "Expected 2 to be between 0 and 1"); 88 | }); 89 | }); 90 | 91 | }); 92 | }} 93 | -------------------------------------------------------------------------------- /oleaster-examples/src/test/java/com/mscharhag/oleaster/examples/MatcherExamplesTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.examples; 2 | 3 | import com.mscharhag.oleaster.runner.OleasterRunner; 4 | import org.junit.runner.RunWith; 5 | 6 | import java.util.regex.Pattern; 7 | 8 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 9 | import static com.mscharhag.oleaster.matcher.Matchers.*; 10 | 11 | /** 12 | * This test shows how Oleaster Matchers can be used. 13 | * These examples are also shown on the Oleaster Matcher documentation page. 14 | * If changes in this file are made, the documentation needs be updated. 15 | */ 16 | @RunWith(OleasterRunner.class) 17 | public class MatcherExamplesTest {{ 18 | 19 | it("gives a quick overview", () -> { 20 | 21 | // same as JUnit's assertEquals(40 + 2, 42) 22 | expect(40 + 2).toEqual(42); 23 | 24 | // see if a String matches a regular expression 25 | expect("foobar").toMatch("fo{2}\\w+"); 26 | 27 | // test exceptions with Java 8 Lambdas 28 | expect(() -> { 29 | // code that throws IllegalArgumentException 30 | throw new IllegalArgumentException(); 31 | }).toThrow(IllegalArgumentException.class); 32 | }); 33 | 34 | it("shows how numbers can be validated", () -> { 35 | int value = 42; 36 | 37 | // check for exact value 38 | expect(value).toEqual(42); 39 | 40 | // check for greater/smaller values 41 | expect(value).toBeGreaterThan(41); 42 | expect(value).toBeSmallerThan(43); 43 | 44 | // check for range 45 | expect(value).toBeBetween(40, 45); 46 | 47 | // floating point number can often not be precisely represented by float/double values. 48 | // So make sure to compare them with an absolute error (delta) 49 | expect(42.0000001).toBeCloseTo(42); // uses default delta of 0.00001 50 | expect(42.0000001).toBeCloseTo(42, 0.000001); 51 | }); 52 | 53 | it("shows how boolean values can be validated", () -> { 54 | boolean value = true; 55 | 56 | // check for a given parameter 57 | expect(value).toEqual(true); 58 | 59 | // check if true 60 | expect(value).toBeTrue(); 61 | 62 | // check if false 63 | value = false; 64 | expect(value).toBeFalse(); 65 | }); 66 | 67 | it("shows how Objects can be validated", () -> { 68 | Person person = new Person("John", "Smith"); 69 | 70 | // check for equality, delegates to Person.equals() 71 | expect(person).toEqual(new Person("John", "Smith")); 72 | 73 | // check if not null 74 | expect(person).toBeNotNull(); 75 | 76 | // check if null 77 | person = null; 78 | expect(person).toBeNull(); 79 | }); 80 | 81 | it("shows how Strings can be validated", () -> { 82 | // check for exact value 83 | expect("foo").toEqual("foo"); 84 | 85 | // check string starting/ending 86 | expect("foobar").toStartWith("foo"); 87 | expect("foobar").toEndWith("bar"); 88 | 89 | // check if a String contains a given substring 90 | expect("foobar").toContain("oba"); 91 | 92 | // check if a String matches a regular expression 93 | expect("foobar").toMatch(Pattern.compile("fo+\\w*")); 94 | expect("foobar").toMatch("fo+\\w*"); 95 | }); 96 | 97 | it("shows how Exceptions can be tested", () -> { 98 | // check if an exception is thrown 99 | expect(() -> { 100 | // code that throws IllegalArgumentException 101 | throw new IllegalArgumentException(); 102 | }).toThrow(IllegalArgumentException.class); 103 | 104 | // with exception message 105 | expect(() -> { 106 | // code that throws IllegalArgumentException 107 | throw new IllegalArgumentException("An argument is invalid"); 108 | }).toThrow(IllegalArgumentException.class, "An argument is invalid"); 109 | }); 110 | 111 | }} 112 | -------------------------------------------------------------------------------- /oleaster-runner/src/main/java/com/mscharhag/oleaster/runner/suite/Suite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.runner.suite; 17 | 18 | import com.mscharhag.oleaster.runner.Invokable; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | public class Suite { 24 | 25 | private Suite parent; 26 | private String description; 27 | 28 | private List suites = new ArrayList<>(); 29 | private List specs = new ArrayList<>(); 30 | private List beforeEachHandlers = new ArrayList<>(); 31 | private List beforeHandlers = new ArrayList<>(); 32 | private List afterEachHandlers = new ArrayList<>(); 33 | private List afterHandlers = new ArrayList<>(); 34 | 35 | 36 | public Suite(Suite parent, String description) { 37 | this.parent = parent; 38 | this.description = description; 39 | } 40 | 41 | public void addBeforeEachHandler(Invokable block) { 42 | beforeEachHandlers.add(block); 43 | } 44 | 45 | public void addAfterEachHandler(Invokable block) { 46 | afterEachHandlers.add(block); 47 | } 48 | 49 | public void addBeforeEachHandlers(List calls) { 50 | this.beforeEachHandlers.addAll(calls); 51 | } 52 | 53 | public void addBeforeHandler(Invokable block) { 54 | this.beforeHandlers.add(block); 55 | } 56 | 57 | public void addBeforeHandlers(List calls) { 58 | this.beforeHandlers.addAll(calls); 59 | } 60 | 61 | public void addAfterHandler(Invokable block) { 62 | this.afterHandlers.add(block); 63 | } 64 | 65 | public void addAfterHandlers(List calls) { 66 | this.afterHandlers.addAll(calls); 67 | } 68 | 69 | public void addAfterEachHandlers(List calls) { 70 | this.afterEachHandlers.addAll(calls); 71 | } 72 | 73 | public void addSpec(Spec spec) { 74 | this.specs.add(spec); 75 | } 76 | 77 | public Suite getParent() { 78 | return parent; 79 | } 80 | 81 | public void addChildSuite(Suite child) { 82 | this.suites.add(child); 83 | } 84 | 85 | public List getBeforeEachHandlers() { 86 | return this.beforeEachHandlers; 87 | } 88 | 89 | public List getBeforeHandlers() { 90 | return this.beforeHandlers; 91 | } 92 | 93 | public List getAfterEachHandlers() { 94 | return this.afterEachHandlers; 95 | } 96 | 97 | public List getAfterHandlers() { 98 | return this.afterHandlers; 99 | } 100 | 101 | 102 | public List collectSpecs() { 103 | List allSpecs = new ArrayList<>(this.specs); 104 | this.suites.forEach(suite -> allSpecs.addAll(suite.collectSpecs())); 105 | return allSpecs; 106 | } 107 | 108 | public String getDescription() { 109 | return description; 110 | } 111 | 112 | public String getFullDescription() { 113 | if (this.parent != null) { 114 | String parentDescription = this.parent.getFullDescription(); 115 | if (parentDescription != null) { 116 | return String.format("%s, %s", parentDescription, this.description); 117 | } 118 | } 119 | return this.description; 120 | } 121 | 122 | public List getSuites() { 123 | return suites; 124 | } 125 | 126 | public List getSpecs() { 127 | return specs; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/CollectionMatcher.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher.matchers; 2 | 3 | import com.mscharhag.oleaster.matcher.util.Arguments; 4 | 5 | import java.util.Collection; 6 | 7 | import static com.mscharhag.oleaster.matcher.util.Expectations.expectNotNull; 8 | import static com.mscharhag.oleaster.matcher.util.Expectations.expectTrue; 9 | 10 | /** 11 | * Matcher class to validate Collections 12 | */ 13 | public class CollectionMatcher extends ObjectMatcher { 14 | 15 | public CollectionMatcher(final Collection value) { 16 | super(value); 17 | } 18 | 19 | /** 20 | * Checks if the stored {@code Collection} contains the provided item. 21 | *

This method throws an {@code AssertionError} if 22 | *

    23 | *
  • the stored {@code Collection} does not contain the passed {@code item}
  • 24 | *
  • the given {@code Collection} is {@code null}
  • 25 | *
26 | * @param item the {@code Object} which the {@code Collection} should contain. 27 | */ 28 | public void toContain(final Object item) { 29 | expectNotNull(this.getValue(), "Expected null to contain '%s'", item); 30 | expectTrue(this.getValue().contains(item), "Expected '%s' to contain '%s'", this.getValue(), item); 31 | } 32 | 33 | /** 34 | * Checks if the stored {@code Collection} does not contain the provided item. 35 | *

This method throws an {@code AssertionError} if 36 | *

    37 | *
  • the stored {@code Collection} does contain the passed {@code item}
  • 38 | *
  • the given {@code Collection} is {@code null}
  • 39 | *
40 | * @param item the {@code Object} which the {@code Collection} should not contain. 41 | */ 42 | public void toNotContain(final Object item) { 43 | expectNotNull(this.getValue(), "Expected null to not contain '%s'", item); 44 | expectTrue(!this.getValue().contains(item), "Expected '%s' to not contain '%s'", this.getValue(), item); 45 | } 46 | 47 | /** 48 | * Checks if the given {@code Collection} is empty 49 | *

This method throws an {@code AssertionError} if 50 | *

    51 | *
  • the stored {@code Collection} is not empty
  • 52 | *
  • the given {@code Collection} is {@code null}
  • 53 | *
54 | */ 55 | public void toBeEmpty() { 56 | expectNotNull(this.getValue(), "Expected null to be empty"); 57 | expectTrue(this.getValue().isEmpty(), "Expected '%s' to be empty", this.getValue()); 58 | } 59 | 60 | /** 61 | * Checks if the given {@code Collection} is not empty 62 | *

This method throws an {@code AssertionError} if 63 | *

    64 | *
  • the stored {@code Collection} is empty
  • 65 | *
  • the given {@code Collection} is {@code null}
  • 66 | *
67 | */ 68 | public void toNotBeEmpty() { 69 | expectNotNull(this.getValue(), "Expected null to not be empty"); 70 | expectTrue(!this.getValue().isEmpty(), "Expected '%s' to not be empty", this.getValue()); 71 | } 72 | 73 | /** 74 | * Checks if the given {@code Collection} has the expected size 75 | *

This method throws an {@code AssertionError} if 76 | *

    77 | *
  • the stored {@code Collection} has a different size than the passed value
  • 78 | *
  • the stored {@code Collection} is {@code null}
  • 79 | *
80 | * @param size The expected size of the collection 81 | */ 82 | public void toHaveSize(final int size) { 83 | expectNotNull(this.getValue(), "Expected null to have size '%d'", size); 84 | expectTrue(this.getValue().size() == size, "Expected '%s' to have a size of %d, " + 85 | "instead has a size of %d", this.getValue(), size, this.getValue().size()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /oleaster-runner/src/test/java/com/mscharhag/oleaster/runner/SuiteBuilderTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.runner; 2 | 3 | import java.util.Arrays; 4 | import java.util.Optional; 5 | 6 | import com.mscharhag.oleaster.runner.suite.SuiteBuilder; 7 | 8 | import org.junit.runner.RunWith; 9 | 10 | import static com.mscharhag.oleaster.runner.AssertUtil.*; 11 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 12 | import static org.junit.Assert.*; 13 | 14 | @RunWith(OleasterRunner.class) 15 | public class SuiteBuilderTest { 16 | 17 | private Invokable invokable = () -> {}; 18 | private SuiteBuilder suiteBuilder; 19 | { 20 | describe("SuiteBuilder", () -> { 21 | 22 | beforeEach(() -> { 23 | suiteBuilder = new SuiteBuilder(); 24 | }); 25 | 26 | it("initialize new SuiteBuilders with empty collections", () -> { 27 | assertEmptySuiteBuilderCollections(suiteBuilder); 28 | }); 29 | 30 | it("empties existing collections before an evaluation", () -> { 31 | // fill collections 32 | suiteBuilder.describe("test suite", invokable); 33 | suiteBuilder.before(invokable); 34 | suiteBuilder.beforeEach(invokable); 35 | suiteBuilder.afterEach(invokable); 36 | suiteBuilder.after(invokable); 37 | suiteBuilder.it("test spec", invokable); 38 | 39 | suiteBuilder.beforeEvaluation(); 40 | assertEmptySuiteBuilderCollections(suiteBuilder); 41 | }); 42 | 43 | describe("when a suite is created", () -> { 44 | beforeEach(() -> { 45 | suiteBuilder.describe("new suite", invokable); 46 | }); 47 | 48 | it("adds a single suite definition", () -> { 49 | assertEquals(1, suiteBuilder.getSuiteDefinitions().size()); 50 | }); 51 | 52 | it("returns the new suite definition", () -> { 53 | assertEquals(invokable, suiteBuilder.getSuiteDefinitions().get("new suite")); 54 | }); 55 | 56 | it("is not possible to add another suite with the same name", () -> { 57 | expect(() -> { 58 | suiteBuilder.describe("new suite", invokable); 59 | }).toFailWith(IllegalArgumentException.class); 60 | }); 61 | }); 62 | 63 | describe("when a spec is created", () -> { 64 | beforeEach(() -> { 65 | suiteBuilder.it("new spec", invokable); 66 | }); 67 | 68 | it("returns the new spec", () -> { 69 | assertEquals(Optional.of(invokable), suiteBuilder.getSpecDefinitions().get("new spec")); 70 | }); 71 | 72 | it("is not possible to add another spec with the same name", () -> { 73 | expect(() -> { 74 | suiteBuilder.it("new spec", invokable); 75 | }).toFailWith(IllegalArgumentException.class); 76 | }); 77 | }); 78 | 79 | describe("when a beforeEach handler is added", () -> { 80 | beforeEach(() -> { 81 | suiteBuilder.beforeEach(invokable); 82 | }); 83 | 84 | it("returns the newly added handler", () -> { 85 | assertEquals(Arrays.asList(invokable), suiteBuilder.getBeforeEachHandlers()); 86 | }); 87 | }); 88 | 89 | describe("when a before handler is added", () -> { 90 | beforeEach(() -> { 91 | suiteBuilder.before(invokable); 92 | }); 93 | 94 | it("returns the newly added handler", () -> { 95 | assertEquals(Arrays.asList(invokable), suiteBuilder.getBeforeHandlers()); 96 | }); 97 | }); 98 | 99 | describe("when a afterEach handler is added", () -> { 100 | beforeEach(() -> { 101 | suiteBuilder.afterEach(invokable); 102 | }); 103 | 104 | it("returns the newly added handler", () -> { 105 | assertEquals(Arrays.asList(invokable), suiteBuilder.getAfterEachHandlers()); 106 | }); 107 | }); 108 | 109 | describe("when a after handler is added", () -> { 110 | beforeEach(() -> { 111 | suiteBuilder.after(invokable); 112 | }); 113 | 114 | it("returns the newly added handler", () -> { 115 | assertEquals(Arrays.asList(invokable), suiteBuilder.getAfterHandlers()); 116 | }); 117 | }); 118 | }); 119 | }} 120 | -------------------------------------------------------------------------------- /oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/ExceptionMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.matcher.matchers; 17 | 18 | import com.mscharhag.oleaster.matcher.util.Arguments; 19 | import com.mscharhag.oleaster.matcher.util.Expectations; 20 | 21 | /** 22 | * Matcher class to validate if a code block throws an exception. 23 | */ 24 | public class ExceptionMatcher { 25 | 26 | private Exception exception; 27 | 28 | /** 29 | * Creates a new {@code ExceptionMatcher} that runs the passed {@code CodeBlock}. 30 | * @param block the code block that should throw an exception 31 | */ 32 | public ExceptionMatcher(CodeBlock block) { 33 | this.exception = null; 34 | this.runCodeBlock(block); 35 | } 36 | 37 | /** 38 | * Checks if an exception of type {@code expectedExceptionClass} was thrown. 39 | *

This method throws an {@code AssertionError} if: 40 | *

    41 | *
  • no exception was thrown.
  • 42 | *
  • the thrown exception is not an instance of {@code expectedExceptionClass}
  • 43 | *
44 | * @param expectedExceptionClass the expected exception 45 | */ 46 | public void toThrow(Class expectedExceptionClass) { 47 | Arguments.ensureNotNull(expectedExceptionClass, "expectedExceptionClass cannot be null"); 48 | String expectedExceptionName = expectedExceptionClass.getName(); 49 | Expectations.expectNotNull(this.exception, "Expected code block to throw %s but it did not throw an exception", 50 | expectedExceptionName); 51 | String exceptionName = this.exception.getClass().getName(); 52 | Expectations.expectTrue(expectedExceptionClass.isInstance(this.exception), 53 | "Expected code block to throw %s but it did throw %s", expectedExceptionName, exceptionName); 54 | } 55 | 56 | /** 57 | * Checks if an exception of type {@code expectedExceptionClass} with message {@code expectedMessage} was thrown. 58 | *

This method throws an {@code AssertionError} if: 59 | *

    60 | *
  • no exception was thrown.
  • 61 | *
  • the thrown exception is not an instance of {@code expectedExceptionClass}
  • 62 | *
  • the message of the thrown exception is not equal {@code expectedMessage}
  • 63 | *
64 | * @param expectedExceptionClass the expected exception 65 | * @param expectedMessage the expected message 66 | */ 67 | public void toThrow(Class expectedExceptionClass, String expectedMessage) { 68 | Arguments.ensureNotNull(expectedMessage, "expectedMessage cannot be null"); 69 | this.toThrow(expectedExceptionClass); 70 | String exceptionMessage = this.exception.getMessage(); 71 | Expectations.expectTrue(expectedMessage.equals(exceptionMessage), 72 | "Expected exception message '%s' but was '%s'", expectedMessage, exceptionMessage); 73 | } 74 | 75 | private void runCodeBlock(CodeBlock block) { 76 | try { 77 | block.run(); 78 | } catch (Exception e) { 79 | this.exception = e; 80 | } 81 | } 82 | 83 | /** 84 | * {@code CodeBlock} represents the piece of code that should throw an exception. 85 | *

{@code CodeBlock} is a functional interface that is typically implemented using 86 | * Java 8 Lambda expressions. Its single method {@code run()} can throw checked exceptions. 87 | */ 88 | public static interface CodeBlock { 89 | public void run() throws Exception; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/matchers/datetime/DateMatcherTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher.matchers.datetime; 2 | 3 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 4 | 5 | import com.mscharhag.oleaster.matcher.TestUtil; 6 | import com.mscharhag.oleaster.runner.OleasterRunner; 7 | import org.junit.runner.RunWith; 8 | 9 | import java.text.ParseException; 10 | import java.text.SimpleDateFormat; 11 | import java.util.Date; 12 | 13 | @RunWith(OleasterRunner.class) 14 | public class DateMatcherTest { 15 | private DateMatcher matcher; 16 | 17 | private Date date(String text) { 18 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 19 | try { 20 | return format.parse(text); 21 | } catch (ParseException e) { 22 | throw new RuntimeException(e); 23 | } 24 | } 25 | { 26 | describe("DateMatcher tests", () -> { 27 | beforeEach(() -> { 28 | matcher = new DateMatcher(date("2015-06-05 12:30:00")); 29 | }); 30 | 31 | 32 | describe("when toBeBefore() is called", () -> { 33 | it("is ok if the stored date is before the passed date", () -> { 34 | matcher.toBeBefore(date("2015-06-05 12:31:00")); 35 | }); 36 | 37 | it("fails if the stored date is equal to the passed date", () -> { 38 | TestUtil.expectAssertionError(() -> matcher.toBeBefore(date("2015-06-05 12:30:00")), 39 | "Expected '2015-06-05 12:30:00.000' to be before '2015-06-05 12:30:00.000'"); 40 | }); 41 | 42 | it("fails if the stored date is after the passed date", () -> { 43 | TestUtil.expectAssertionError(() -> matcher.toBeBefore(date("2015-06-05 12:29:00")), 44 | "Expected '2015-06-05 12:30:00.000' to be before '2015-06-05 12:29:00.000'"); 45 | }); 46 | }); 47 | 48 | describe("when toBeAfter() is called", () -> { 49 | it("is ok if the stored date is after the passed date", () -> { 50 | matcher.toBeAfter(date("2015-06-05 12:29:00")); 51 | }); 52 | 53 | it("fails if the stored date is equal to the passed date", () -> { 54 | TestUtil.expectAssertionError(() -> matcher.toBeAfter(date("2015-06-05 12:30:00")), 55 | "Expected '2015-06-05 12:30:00.000' to be after '2015-06-05 12:30:00.000'"); 56 | }); 57 | 58 | it("fails if the stored date is before the passed date", () -> { 59 | TestUtil.expectAssertionError(() -> matcher.toBeAfter(date("2015-06-05 12:31:00")), 60 | "Expected '2015-06-05 12:30:00.000' to be after '2015-06-05 12:31:00.000'"); 61 | }); 62 | }); 63 | 64 | describe("when toBeBetween() is called", () -> { 65 | it("is ok if the stored date is between the passed values", () -> { 66 | matcher.toBeBetween(date("2015-06-05 12:29:00"), date("2015-06-05 12:31:00")); 67 | }); 68 | 69 | it("is ok if the stored date is equal to the lower value", () -> { 70 | matcher.toBeBetween(date("2015-06-05 12:30:00"), date("2015-06-05 12:31:00")); 71 | }); 72 | 73 | it("fails if the stored date is before the lower value", () -> { 74 | TestUtil.expectAssertionError(() -> matcher.toBeBetween(date("2015-06-05 12:31:00"), date("2015-06-05 12:32:00")), 75 | "Expected '2015-06-05 12:30:00.000' to be between '2015-06-05 12:31:00.000' and '2015-06-05 12:32:00.000'"); 76 | }); 77 | 78 | it("fails if the stored date is after the upper value", () -> { 79 | TestUtil.expectAssertionError(() -> matcher.toBeBetween(date("2015-06-05 12:28:00"), date("2015-06-05 12:29:00")), 80 | "Expected '2015-06-05 12:30:00.000' to be between '2015-06-05 12:28:00.000' and '2015-06-05 12:29:00.000'"); 81 | }); 82 | }); 83 | 84 | describe("when toBeCloseTo() is called", () -> { 85 | it("is ok if the stored date is closed to the passed value", () -> { 86 | matcher.toBeCloseTo(date("2015-06-05 12:29:59"), 1001); 87 | }); 88 | 89 | it("fails if the stored date is not close to the passed value", () -> { 90 | TestUtil.expectAssertionError(() -> matcher.toBeCloseTo(date("2015-06-05 12:29:59"), 999), 91 | "Expected '2015-06-05 12:30:00.000' to be close to '2015-06-05 12:29:59.000', delta: 999ms"); 92 | }); 93 | }); 94 | }); 95 | 96 | }} 97 | -------------------------------------------------------------------------------- /oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/StringMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.matcher.matchers; 17 | 18 | import com.mscharhag.oleaster.matcher.util.Arguments; 19 | import static com.mscharhag.oleaster.matcher.util.Expectations.*; 20 | 21 | import java.util.regex.Pattern; 22 | 23 | /** 24 | * Matcher class to validate Strings 25 | */ 26 | public class StringMatcher extends ObjectMatcher { 27 | 28 | 29 | public StringMatcher(String value) { 30 | super(value); 31 | } 32 | 33 | /** 34 | * Checks if the stored {@code String} matches a regular expression. 35 | *

This method throws an {@code AssertionError} if 36 | *

    37 | *
  • the stored {@code String} does not match the passed {@code pattern}
  • 38 | *
  • the stored {@code String} is {@code null}
  • 39 | *
40 | * @param pattern the {@code Pattern} representing the regular expression 41 | * @throws java.lang.IllegalArgumentException if {@code pattern} is {@code null}. 42 | */ 43 | public void toMatch(Pattern pattern) { 44 | Arguments.ensureNotNull(pattern, "pattern cannot be null"); 45 | expectNotNull(this.getValue(), "Expected null to match '%s'", pattern.pattern()); 46 | expectTrue(pattern.matcher(this.getValue()).matches(), 47 | "Expected '%s' to match '%s'", this.getValue(), pattern.pattern()); 48 | } 49 | 50 | /** 51 | * Checks if the stored {@code String} matches a regular expression. 52 | *

This method is similar to {@link #toMatch(java.util.regex.Pattern)} except it takes the regular expression as 53 | * String. The passed String {@code pattern} will be compiled to a {@link java.util.regex.Pattern} using 54 | * {@code Pattern.compile()}. 55 | * @param pattern a {@code String} containing the regular expression. 56 | */ 57 | public void toMatch(String pattern) { 58 | this.toMatch(Pattern.compile(pattern)); 59 | } 60 | 61 | /** 62 | * Checks if the stored {@code String} starts with a given sub string. 63 | *

This method throws an {@code AssertionError} if 64 | *

    65 | *
  • the stored {@code String} does not start with {@code start}
  • 66 | *
  • the stored {@code String} is {@code null}
  • 67 | *
68 | * @throws java.lang.IllegalArgumentException if {@code start} is {@code null}. 69 | * @param start the sub string 70 | */ 71 | public void toStartWith(String start) { 72 | Arguments.ensureNotNull(start, "start cannot be null"); 73 | expectNotNull(this.getValue(), "Expected null to start with '%s'", start); 74 | expectTrue(this.getValue().startsWith(start), "Expected '%s' to start with '%s'", this.getValue(), start); 75 | } 76 | 77 | /** 78 | * Checks if the stored {@code String} ends with a given sub string. 79 | *

This method throws an {@code AssertionError} if 80 | *

    81 | *
  • the stored {@code String} does not end with {@code end}
  • 82 | *
  • the stored {@code String} is {@code null}
  • 83 | *
84 | * @throws java.lang.IllegalArgumentException if {@code end} is {@code null}. 85 | * @param end the sub string 86 | */ 87 | public void toEndWith(String end) { 88 | Arguments.ensureNotNull(end, "end cannot be null"); 89 | expectNotNull(this.getValue(), "Expected null to end with '%s'", end); 90 | expectTrue(this.getValue().endsWith(end), "Expected '%s' to end with '%s'", this.getValue(), end); 91 | } 92 | 93 | 94 | /** 95 | * Checks if the stored {@code String} contains a given sub string. 96 | *

This method throws an {@code AssertionError} if 97 | *

    98 | *
  • the stored {@code String} does not contain {@code substr}
  • 99 | *
  • the stored {@code String} is {@code null}
  • 100 | *
101 | * @throws java.lang.IllegalArgumentException if {@code substr} is {@code null}. 102 | * @param substr the sub string 103 | */ 104 | public void toContain(String substr) { 105 | Arguments.ensureNotNull(substr, "substr cannot be null"); 106 | expectNotNull(this.getValue(), "Expected null to contain '%s'", substr); 107 | expectTrue(this.getValue().contains(substr), "Expected '%s' to contain '%s'", this.getValue(), substr); 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/MapMatcher.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher.matchers; 2 | 3 | import java.util.Map; 4 | 5 | import com.mscharhag.oleaster.matcher.util.Arguments; 6 | 7 | import static com.mscharhag.oleaster.matcher.util.Expectations.expectNotNull; 8 | import static com.mscharhag.oleaster.matcher.util.Expectations.expectTrue; 9 | 10 | /** 11 | * Matcher class to validate {@link Map}s 12 | */ 13 | public class MapMatcher extends ObjectMatcher> { 14 | 15 | public MapMatcher(final Map value) { 16 | super(value); 17 | } 18 | 19 | /** 20 | * Checks if the stored {@code Map} is empty. 21 | *

This method throws an {@code AssertionError} if 22 | *

    23 | *
  • the stored {@code Map} is not empty
  • 24 | *
  • the stored {@code Map} is {@code null}
  • 25 | *
26 | */ 27 | public void toBeEmpty() { 28 | expectNotNull(this.getValue(), "Expected null to be empty"); 29 | expectTrue(this.getValue().isEmpty(), "Expected '%s' to be empty", this.getValue()); 30 | } 31 | 32 | /** 33 | * Checks if the stored {@code Map} is not empty. 34 | *

This method throws an {@code AssertionError} if 35 | *

    36 | *
  • the stored {@code Map} is empty
  • 37 | *
  • the stored {@code Map} is {@code null}
  • 38 | *
39 | */ 40 | public void toNotBeEmpty() { 41 | expectNotNull(this.getValue(), "Expected null to not be empty"); 42 | expectTrue(!this.getValue().isEmpty(), "Expected '%s' to not be empty", this.getValue()); 43 | } 44 | 45 | /** 46 | * Checks if the stored {@code Map} contains the given {@code key}. 47 | *

This method throws an {@code AssertionError} if 48 | *

    49 | *
  • the stored {@code Map} does not contain the given {@code key}
  • 50 | *
  • the stored {@code Map} is {@code null}
  • 51 | *
52 | * @param key the expected key 53 | */ 54 | public void toContainKey(final K key) { 55 | expectNotNull(this.getValue(), "Expected null to contain the key '%s'", key); 56 | expectTrue(this.getValue().containsKey(key), "Expected '%s' to contain key '%s'", this.getValue(), key); 57 | } 58 | 59 | /** 60 | * Checks if the stored {@code Map} does not contain the given {@code key}. 61 | *

This method throws an {@code AssertionError} if 62 | *

    63 | *
  • the stored {@code Map} contains the given {@code key}
  • 64 | *
  • the stored {@code Map} is {@code null}
  • 65 | *
66 | * @param key the expected key 67 | */ 68 | public void toNotContainKey(final K key) { 69 | expectNotNull(this.getValue(), "Expected null to not contain the key '%s'", key); 70 | expectTrue(!this.getValue().containsKey(key), "Expected '%s' to not contain key '%s'", this.getValue(), key); 71 | } 72 | 73 | /** 74 | * Checks if the stored {@code Map} contains the given {@code value}. 75 | *

This method throws an {@code AssertionError} if 76 | *

    77 | *
  • the stored {@code Map} does not contain the given {@code value}
  • 78 | *
  • the stored {@code Map} is {@code null}
  • 79 | *
80 | * @param value the expected value 81 | */ 82 | public void toContainValue(final V value) { 83 | expectNotNull(this.getValue(), "Expected null to contain the value '%s'", value); 84 | expectTrue(this.getValue().containsValue(value), "Expected '%s' to contain value '%s'", this.getValue(), value); 85 | } 86 | 87 | /** 88 | * Checks if the stored {@code Map} does not contain the given {@code value}. 89 | *

This method throws an {@code AssertionError} if 90 | *

    91 | *
  • the stored {@code Map} does not contain the given {@code value}
  • 92 | *
  • the stored {@code Map} is {@code null}
  • 93 | *
94 | * @param value the expected value 95 | */ 96 | public void toNotContainValue(final V value) { 97 | expectNotNull(this.getValue(), "Expected null to not contain the value '%s'", value); 98 | expectTrue(!this.getValue().containsValue(value), "Expected '%s' to not contain value '%s'", this.getValue(), value); 99 | } 100 | 101 | /** 102 | * Checks if the stored {@code Map} has a given {@code size}. 103 | *

This method throws an {@code AssertionError} if 104 | *

    105 | *
  • the stored {@code Map} does not have the given {@code size}
  • 106 | *
  • the stored {@code Map} is {@code null}
  • 107 | *
108 | * @param size the expected size 109 | */ 110 | public void toHaveSize(final int size) { 111 | expectNotNull(this.getValue(), "Expected null to have size '%s'", size); 112 | expectTrue(this.getValue().size() == size, "Expected '%s' to have a size of %d, instead has a size of %d", this.getValue(), size, this.getValue().size()); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/FloatingPointNumberMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.matcher.matchers; 17 | 18 | import com.mscharhag.oleaster.matcher.util.Arguments; 19 | import com.mscharhag.oleaster.matcher.util.Expectations; 20 | 21 | /** 22 | * Matcher class to validate floating point numbers numbers 23 | */ 24 | public class FloatingPointNumberMatcher { 25 | 26 | private double value; 27 | 28 | /** 29 | * Creates a new {@code FloatingPointNumberMatcher} to validate the passed {@code value}. 30 | * @param value the value that should be validated 31 | */ 32 | public FloatingPointNumberMatcher(double value) { 33 | this.value = value; 34 | } 35 | 36 | /** 37 | * Checks if the stored value is equal to another value. 38 | *

This method throws an {@code AssertionError} if the stored value is not equal to {@code other}. 39 | *

Note:In most situations floating point numbers should not be checked for equality. 40 | * If you want to check if the stored value is nearly the same as another value use 41 | * {@link #toBeCloseTo(double, double)} instead. 42 | * @param other the value to compare with 43 | * @see #toBeCloseTo(double, double) 44 | */ 45 | public void toEqual(double other) { 46 | Expectations.expectTrue(this.value == other, "Expected %s to equal %s", this.value, other); 47 | } 48 | 49 | /** 50 | * Checks if the stored value is close to another value. 51 | *

This method throws an {@code AssertionError} if the difference between the stored value and {@code other} is 52 | * greater than {@code delta}. 53 | * @param other the value to compare with 54 | * @param delta the delta 55 | */ 56 | public void toBeCloseTo(double other, double delta) { 57 | boolean isCloseTo = this.value >= other - delta && this.value <= other + delta; 58 | Expectations.expectTrue(isCloseTo, "Expected %s to be close to %s with delta %s", this.value, other, delta); 59 | } 60 | 61 | /** 62 | * Checks if the stored value is close to another value. 63 | *

Similar to {@link #toBeCloseTo(double, double)} but uses a default delta of {@code 0.00001}. 64 | *

This method throws an {@code AssertionError} if the difference between the stored value and {@code other} is 65 | * greater than {@code 0.00001}. 66 | * @param other the value to compare with 67 | */ 68 | public void toBeCloseTo(double other) { 69 | this.toBeCloseTo(other, 0.00001); 70 | } 71 | 72 | /** 73 | * Checks if the stored value is greater than another value. 74 | *

This method throws an {@code AssertionError} if: 75 | *

    76 | *
  • the stored value is smaller than {@code other}
  • 77 | *
  • the stored value is equal to {@code other}
  • 78 | *
79 | * @param other the value to compare with 80 | */ 81 | public void toBeGreaterThan(double other) { 82 | Expectations.expectTrue(this.value > other, "Expected %s to be greater than %s", this.value, other); 83 | } 84 | 85 | /** 86 | * Checks if the stored value is smaller than another value. 87 | *

This method throws an {@code AssertionError} if: 88 | *

    89 | *
  • the stored value is greater than {@code other}
  • 90 | *
  • the stored value is equal to {@code other}
  • 91 | *
92 | * @param other the value to compare with 93 | */ 94 | public void toBeSmallerThan(double other) { 95 | Expectations.expectTrue(this.value < other, "Expected %s to be smaller than %s", this.value, other); 96 | } 97 | 98 | /** 99 | * Checks if the stored value is between a lower and an upper bound. 100 | *

This method throws an {@code AssertionError} if: 101 | *

    102 | *
  • the stored value is smaller than the lower bound
  • 103 | *
  • the stored value is greater than the upper bound
  • 104 | *
105 | *

It is ok if the stored value is equal to the lower or the upper bound 106 | * @param lower the lower bound 107 | * @param upper the upper bound 108 | * @throws java.lang.IllegalArgumentException if {@code lower} is not smaller than {@code upper} 109 | */ 110 | public void toBeBetween(double lower, double upper) { 111 | Arguments.ensureTrue(lower < upper, "upper has to be greater than lower"); 112 | boolean isBetween = this.value >= lower && this.value <= upper; 113 | Expectations.expectTrue(isBetween, "Expected %s to be between %s and %s", this.value, lower, upper); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/matchers/FloatingPointNumberMatcherTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher.matchers; 2 | 3 | import com.mscharhag.oleaster.matcher.TestUtil; 4 | import com.mscharhag.oleaster.runner.OleasterRunner; 5 | import org.junit.runner.RunWith; 6 | 7 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 8 | import static org.junit.Assert.assertTrue; 9 | 10 | @RunWith(OleasterRunner.class) 11 | public class FloatingPointNumberMatcherTest {{ 12 | describe("FloatingPointNumberMatcher test", () -> { 13 | 14 | describe("when toEqual() is called", () -> { 15 | it("fails if both values are not equal", () -> { 16 | TestUtil.expectAssertionError(() -> new FloatingPointNumberMatcher(1.5).toEqual(2.5), 17 | "Expected 1.5 to equal 2.5"); 18 | }); 19 | 20 | it("is ok if both values are equal", () -> { 21 | new FloatingPointNumberMatcher(1.5).toEqual(1.5); 22 | }); 23 | }); 24 | 25 | describe("when toBeGreaterThan() is called", () -> { 26 | it("fails if the passed value greater", () -> { 27 | TestUtil.expectAssertionError(() -> new FloatingPointNumberMatcher(1.5).toBeGreaterThan(1.6), 28 | "Expected 1.5 to be greater than 1.6"); 29 | }); 30 | 31 | it("fails if both values are equal", () -> { 32 | TestUtil.expectAssertionError(() -> new FloatingPointNumberMatcher(1.5).toBeGreaterThan(1.5), 33 | "Expected 1.5 to be greater than 1.5"); 34 | }); 35 | 36 | it("is ok if the passed value is smaller", () -> { 37 | new FloatingPointNumberMatcher(1.5).toBeGreaterThan(1.4); 38 | }); 39 | }); 40 | 41 | describe("when toBeSmallerThan() is called", () -> { 42 | it("fails if the passed value smaller", () -> { 43 | TestUtil.expectAssertionError(() -> new FloatingPointNumberMatcher(1.5).toBeSmallerThan(1.4), 44 | "Expected 1.5 to be smaller than 1.4"); 45 | }); 46 | 47 | it("fails if both values are equal", () -> { 48 | TestUtil.expectAssertionError(() -> new FloatingPointNumberMatcher(1.5).toBeSmallerThan(1.5), 49 | "Expected 1.5 to be smaller than 1.5"); 50 | }); 51 | 52 | it("is ok if the passed value is greater", () -> { 53 | new FloatingPointNumberMatcher(1.5).toBeSmallerThan(1.6); 54 | }); 55 | }); 56 | 57 | describe("when toBeBetween() is called", () -> { 58 | it("throws an exception if the lower bound is greater than the upper bound", () -> { 59 | Exception ex = TestUtil.catchException(() -> new FloatingPointNumberMatcher(1.5).toBeBetween(1.6, 1.4)); 60 | assertTrue(ex instanceof IllegalArgumentException); 61 | }); 62 | 63 | it("throws an exception if the lower bound is equal to the upper bound", () -> { 64 | Exception ex = TestUtil.catchException(() -> new FloatingPointNumberMatcher(1.5).toBeBetween(1.4, 1.4)); 65 | assertTrue(ex instanceof IllegalArgumentException); 66 | }); 67 | 68 | it("fails if the value smaller than the lower bound", () -> { 69 | TestUtil.expectAssertionError(() -> new FloatingPointNumberMatcher(1.5).toBeBetween(1.6, 1.7), 70 | "Expected 1.5 to be between 1.6 and 1.7"); 71 | }); 72 | 73 | it("is ok if the value is equal to the lower bound", () -> { 74 | new FloatingPointNumberMatcher(1.5).toBeBetween(1.5, 1.6); 75 | }); 76 | 77 | it("is ok if the value is greater than the lower bound and lower than the upper bound", () -> { 78 | new FloatingPointNumberMatcher(1.5).toBeBetween(1.4, 1.6); 79 | }); 80 | 81 | it("is ok if the value is equal to the upper bound", () -> { 82 | new FloatingPointNumberMatcher(1.5).toBeBetween(1.4, 1.5); 83 | }); 84 | 85 | it("fails if the value is greater than the upper bound", () -> { 86 | TestUtil.expectAssertionError(() -> new FloatingPointNumberMatcher(1.5).toBeBetween(1.3, 1.4), 87 | "Expected 1.5 to be between 1.3 and 1.4"); 88 | }); 89 | }); 90 | 91 | describe("when toBeCloseTo() without delta parameter is used", () -> { 92 | it("is ok if the value is greater but the delta is smaller than 0.00001", () -> { 93 | new FloatingPointNumberMatcher(1.500009).toBeCloseTo(1.5); 94 | }); 95 | 96 | it("is ok if the value is smaller but the delta is smaller than 0.00001", () -> { 97 | new FloatingPointNumberMatcher(1.49999).toBeCloseTo(1.5); 98 | }); 99 | 100 | it("fails if the the delta of 0.00001 is exceeded", () -> { 101 | TestUtil.expectAssertionError(() -> new FloatingPointNumberMatcher(1.4999).toBeCloseTo(1.5), 102 | "Expected 1.4999 to be close to 1.5 with delta 1.0E-5"); 103 | }); 104 | }); 105 | 106 | describe("when toBeCloseTo() with a delta parameter is used", () -> { 107 | it("is ok if the delta is smaller than the passed value", () -> { 108 | new FloatingPointNumberMatcher(1.549).toBeCloseTo(1.5, 0.05); 109 | }); 110 | 111 | it("fails if the the delta is exceeded", () -> { 112 | TestUtil.expectAssertionError(() -> new FloatingPointNumberMatcher(1.551).toBeCloseTo(1.5, 0.05), 113 | "Expected 1.551 to be close to 1.5 with delta 0.05"); 114 | }); 115 | }); 116 | 117 | }); 118 | }} 119 | -------------------------------------------------------------------------------- /oleaster-runner/src/main/java/com/mscharhag/oleaster/runner/suite/SuiteBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.runner.suite; 17 | 18 | 19 | import java.util.ArrayList; 20 | import java.util.LinkedHashMap; 21 | import java.util.List; 22 | import java.util.Map; 23 | import java.util.Optional; 24 | 25 | import com.mscharhag.oleaster.runner.Invokable; 26 | import com.mscharhag.oleaster.runner.PendingInvokable; 27 | 28 | public class SuiteBuilder { 29 | 30 | private Map suiteDefinitions; 31 | private Map focusedSuiteDefinitions; 32 | private Map> specDefinitions; 33 | private Map> focusedSpecDefinitions; 34 | private List beforeEachHandlers; 35 | private List beforeHandlers; 36 | private List afterEachHandlers; 37 | private List afterHandlers; 38 | 39 | public SuiteBuilder() { 40 | this.prepare(); 41 | } 42 | 43 | private void prepare() { 44 | this.suiteDefinitions = new LinkedHashMap<>(); 45 | this.focusedSuiteDefinitions = new LinkedHashMap<>(); 46 | this.specDefinitions = new LinkedHashMap<>(); 47 | this.focusedSpecDefinitions = new LinkedHashMap<>(); 48 | this.beforeHandlers = new ArrayList<>(); 49 | this.afterHandlers = new ArrayList<>(); 50 | this.beforeEachHandlers = new ArrayList<>(); 51 | this.afterEachHandlers = new ArrayList<>(); 52 | } 53 | 54 | public void beforeEvaluation() { 55 | this.prepare(); 56 | } 57 | 58 | public void afterEvaluation() { 59 | 60 | } 61 | 62 | public void describe(String description, Invokable definition) { 63 | throwExceptionWhenSuiteDescriptionExists(description); 64 | this.suiteDefinitions.put(description, definition); 65 | } 66 | 67 | public void fdescribe(String description, Invokable definition) { 68 | throwExceptionWhenSuiteDescriptionExists(description); 69 | this.focusedSuiteDefinitions.put(description, definition); 70 | } 71 | 72 | public void xdescribe(String description, PendingInvokable definition) { 73 | throwExceptionWhenSuiteDescriptionExists(description); 74 | this.suiteDefinitions.put(description, definition); 75 | } 76 | 77 | private void throwExceptionWhenSuiteDescriptionExists(final String description) { 78 | if (this.suiteDefinitions.containsKey(description) || this.focusedSuiteDefinitions.containsKey(description)) { 79 | throw new IllegalArgumentException(String.format("Suite with description '%s' does already exist", description)); 80 | } 81 | } 82 | 83 | public void it(String description, Invokable definition) { 84 | throwExceptionWhenSpecDescriptionExists(description); 85 | this.specDefinitions.put(description, Optional.of(definition)); 86 | } 87 | 88 | public void fit(String description, Invokable definition) { 89 | throwExceptionWhenSpecDescriptionExists(description); 90 | this.focusedSpecDefinitions.put(description, Optional.of(definition)); 91 | } 92 | 93 | public void xit(String description) { 94 | throwExceptionWhenSpecDescriptionExists(description); 95 | this.specDefinitions.put(description, Optional.empty()); 96 | } 97 | 98 | private void throwExceptionWhenSpecDescriptionExists(final String description) { 99 | if (this.specDefinitions.containsKey(description) || this.focusedSpecDefinitions.containsKey(description)) { 100 | throw new IllegalArgumentException(String.format("Spec with description '%s' does already exist", description)); 101 | } 102 | } 103 | 104 | public void beforeEach(Invokable block) { 105 | this.beforeEachHandlers.add(block); 106 | } 107 | 108 | public void before(Invokable block) { 109 | this.beforeHandlers.add(block); 110 | } 111 | 112 | public void afterEach(Invokable block) { 113 | this.afterEachHandlers.add(block); 114 | } 115 | 116 | public void after(Invokable block) { 117 | this.afterHandlers.add(block); 118 | } 119 | 120 | public Map getSuiteDefinitions() { 121 | return suiteDefinitions; 122 | } 123 | 124 | public Map getFocusedSuiteDefinitions() { 125 | return focusedSuiteDefinitions; 126 | } 127 | 128 | public Map> getSpecDefinitions() { 129 | return specDefinitions; 130 | } 131 | 132 | public Map> getFocusedSpecDefinitions() { 133 | return focusedSpecDefinitions; 134 | } 135 | 136 | public List getBeforeEachHandlers() { 137 | return beforeEachHandlers; 138 | } 139 | 140 | public List getBeforeHandlers() { 141 | return beforeHandlers; 142 | } 143 | 144 | public List getAfterEachHandlers() { 145 | return afterEachHandlers; 146 | } 147 | 148 | public List getAfterHandlers() { 149 | return afterHandlers; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /oleaster-runner/src/test/java/com/mscharhag/oleaster/runner/HandlerTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.runner; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.function.Function; 8 | 9 | import com.mscharhag.oleaster.runner.suite.Spec; 10 | import com.mscharhag.oleaster.runner.suite.Suite; 11 | 12 | import org.junit.Before; 13 | import org.junit.Test; 14 | import org.junit.runner.notification.RunNotifier; 15 | 16 | import static org.junit.Assert.*; 17 | 18 | public class HandlerTest { 19 | 20 | private List calls; 21 | private Function block = (String name) -> () -> { calls.add(name); }; 22 | private OleasterRunner runner; 23 | private Suite suite; 24 | private Spec first; 25 | private Spec second; 26 | private Spec spec; 27 | 28 | public static class TestClass { } 29 | 30 | 31 | @Before 32 | public void before() throws Exception { 33 | calls = new ArrayList<>(); 34 | runner = new OleasterRunner(TestClass.class); 35 | suite = new Suite(null, "suite"); 36 | first = new Spec(suite, "spec", Optional.of(block.apply("first-spec"))); 37 | second = new Spec(suite, "spec", Optional.of(block.apply("second-spec"))); 38 | spec = new Spec(suite, "spec", Optional.of(block.apply("spec"))); 39 | } 40 | 41 | 42 | @Test 43 | public void itExecutesBeforeHandlersBeforeTheFirstSpecIsExecuted() { 44 | suite.addBeforeHandler(block.apply("before")); 45 | suite.addSpec(first); 46 | suite.addSpec(second); 47 | runner.runChild(first, new RunNotifier()); 48 | runner.runChild(second, new RunNotifier()); 49 | assertEquals(Arrays.asList("before", "first-spec", "second-spec"), calls); 50 | } 51 | 52 | 53 | @Test 54 | public void itExecutesAfterHandlersOnceAfterTheLastSpecIsExecuted() { 55 | suite.addAfterHandler(block.apply("after")); 56 | suite.addSpec(first); 57 | suite.addSpec(second); 58 | runner.runChild(first, new RunNotifier()); 59 | runner.runChild(second, new RunNotifier()); 60 | assertEquals(Arrays.asList("first-spec", "second-spec", "after"), calls); 61 | } 62 | 63 | 64 | @Test 65 | public void itExecutesOuterBeforeHandlersBeforeInnerOnes() { 66 | suite.addBeforeHandler(block.apply("outerBefore")); 67 | Suite child = new Suite(suite, "child"); 68 | child.addBeforeHandler(block.apply("innerBefore")); 69 | runner.runChild(new Spec(child, "spec", Optional.of(block.apply("spec"))), new RunNotifier()); 70 | assertEquals(Arrays.asList("outerBefore", "innerBefore", "spec"), calls); 71 | } 72 | 73 | 74 | @Test 75 | public void itExecutesBeforeHandlersInSpecifiedOrder() { 76 | suite.addBeforeHandler(block.apply("first")); 77 | suite.addBeforeHandler(block.apply("second")); 78 | runner.runChild(spec, new RunNotifier()); 79 | assertEquals(Arrays.asList("first", "second", "spec"), calls); 80 | } 81 | 82 | 83 | @Test 84 | public void itExecutesBeforeEachHandlersInSpecifiedOrder() { 85 | suite.addBeforeEachHandler(block.apply("first")); 86 | suite.addBeforeEachHandler(block.apply("second")); 87 | runner.runChild(new Spec(suite, "spec", Optional.of(() -> {})), new RunNotifier()); 88 | assertEquals(Arrays.asList("first", "second"), calls); 89 | } 90 | 91 | 92 | @Test 93 | public void itExecutesAfterEachHandlersInSpecifiedOrder() { 94 | suite.addAfterEachHandler(block.apply("first")); 95 | suite.addAfterEachHandler(block.apply("second")); 96 | runner.runChild(new Spec(suite, "spec", Optional.of(() -> {})), new RunNotifier()); 97 | assertEquals(Arrays.asList("first", "second"), calls); 98 | } 99 | 100 | 101 | @Test 102 | public void itExecutesBeforeEachHandlersBeforeTheSpecIsExecuted() { 103 | suite.addBeforeEachHandler(block.apply("beforeEach")); 104 | runner.runChild(new Spec(suite, "spec", Optional.of(block.apply("spec"))), new RunNotifier()); 105 | assertEquals(Arrays.asList("beforeEach", "spec"), calls); 106 | } 107 | 108 | 109 | @Test 110 | public void itExecutesAfterEachHandlersAfterTheSpecIsExecuted() { 111 | suite.addAfterEachHandler(block.apply("afterEach")); 112 | runner.runChild(new Spec(suite, "spec", Optional.of(block.apply("spec"))), new RunNotifier()); 113 | assertEquals(Arrays.asList("spec", "afterEach"), calls); 114 | } 115 | 116 | 117 | @Test 118 | public void itExecutesOuterBeforeEachHandlersBeforeInnerOnes() { 119 | suite.addBeforeEachHandler(block.apply("outerBeforeEach")); 120 | Suite child = new Suite(suite, "child"); 121 | child.addBeforeEachHandler(block.apply("innerBeforeEach")); 122 | runner.runChild(new Spec(child, "spec", Optional.of(() -> {})), new RunNotifier()); 123 | assertEquals(Arrays.asList("outerBeforeEach", "innerBeforeEach"), calls); 124 | } 125 | 126 | 127 | @Test 128 | public void itExecutesInnerAfterEachHandlersBeforeOuterOnes() { 129 | suite.addAfterEachHandler(block.apply("outerBeforeEach")); 130 | Suite child = new Suite(suite, "child"); 131 | child.addAfterEachHandler(block.apply("innerBeforeEach")); 132 | runner.runChild(new Spec(child, "spec", Optional.of(() -> {})), new RunNotifier()); 133 | assertEquals(Arrays.asList("innerBeforeEach", "outerBeforeEach"), calls); 134 | } 135 | 136 | } 137 | -------------------------------------------------------------------------------- /oleaster-runner/src/main/java/com/mscharhag/oleaster/runner/OleasterRunner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.runner; 17 | 18 | import com.mscharhag.oleaster.runner.suite.SuiteBuilder; 19 | import com.mscharhag.oleaster.runner.suite.Spec; 20 | import com.mscharhag.oleaster.runner.suite.Suite; 21 | import com.mscharhag.oleaster.runner.suite.SuiteDefinition; 22 | import com.mscharhag.oleaster.runner.suite.SuiteDefinitionEvaluator; 23 | import org.junit.runner.Description; 24 | import org.junit.runner.notification.RunNotifier; 25 | import org.junit.runners.ParentRunner; 26 | import org.junit.runners.model.InitializationError; 27 | 28 | import java.util.ArrayList; 29 | import java.util.Collections; 30 | import java.util.List; 31 | import java.util.function.Function; 32 | 33 | /** 34 | * OleasterRunner is JUnit runner that lets you write JUnit tests 35 | * like you write Jasmine tests (a popular Javascript testing framework). 36 | *

An Oleaster test looks like this: 37 | *

 38 |  * 	{@literal @}RunWith(OleasterRunner.class)
 39 |  * 	 public class RunnerIntroductionTest {{
 40 |  *		describe("A suite", () -> {
 41 |  *			it("contains a spec with an expectation", () -> {
 42 |  *				// test code
 43 |  *			});
 44 |  *		});
 45 |  *	}}
 46 |  * 
47 | */ 48 | public class OleasterRunner extends ParentRunner { 49 | 50 | public OleasterRunner(Class testClass) throws InitializationError { 51 | super(testClass); 52 | } 53 | 54 | 55 | @Override 56 | protected List getChildren() { 57 | SuiteBuilder suiteBuilder = this.createSuiteBuilder(); 58 | SuiteDefinition baseSuiteDefinition = this.createBaseSuiteDefinition(suiteBuilder); 59 | SuiteDefinitionEvaluator evaluator = this.createSuiteDefinitionEvaluator(); 60 | 61 | Suite suite = evaluator.evaluate(baseSuiteDefinition, suiteBuilder); 62 | 63 | return suite.collectSpecs(); 64 | } 65 | 66 | 67 | @Override 68 | protected void runChild(Spec spec, RunNotifier notifier) { 69 | List specs = spec.getSuite().getSpecs(); 70 | boolean suiteHasNoSpecs = specs.isEmpty(); 71 | boolean isFirstSpec = specs.indexOf(spec) == 0; 72 | boolean isLastSpec = specs.indexOf(spec) == specs.size() -1; 73 | 74 | if (suiteHasNoSpecs || isFirstSpec){ 75 | runBeforeCallbacks(spec); 76 | } 77 | 78 | if (spec.getBlock().isPresent()) { 79 | runBeforeEachCallbacks(spec); 80 | runLeaf(spec, describeChild(spec), notifier); 81 | runAfterEachCallbacks(spec); 82 | } else { 83 | notifier.fireTestIgnored(describeChild(spec)); 84 | } 85 | 86 | 87 | if (suiteHasNoSpecs || isLastSpec){ 88 | runAfterCallbacks(spec); 89 | } 90 | } 91 | 92 | 93 | @Override 94 | protected Description describeChild(Spec child) { 95 | return Description.createTestDescription(this.getTestClass().getJavaClass(), child.getFullDescription()); 96 | } 97 | 98 | 99 | protected SuiteBuilder createSuiteBuilder() { 100 | return new StaticSupportingSuiteBuilder(); 101 | } 102 | 103 | 104 | protected SuiteDefinition createBaseSuiteDefinition(SuiteBuilder suiteBuilder) { 105 | return new SuiteDefinition(null, null, () -> { 106 | Object obj = getTestClass().getJavaClass().newInstance(); 107 | if (obj instanceof OleasterTest) { 108 | ((OleasterTest) obj).buildTestSuite(suiteBuilder); 109 | } 110 | }); 111 | } 112 | 113 | 114 | protected SuiteDefinitionEvaluator createSuiteDefinitionEvaluator() { 115 | return new SuiteDefinitionEvaluator(); 116 | } 117 | 118 | 119 | private void runBeforeEachCallbacks(Spec spec) { 120 | this.runInvokables(this.collectInvokables(spec.getSuite(), Suite::getBeforeEachHandlers, true)); 121 | } 122 | 123 | 124 | private void runBeforeCallbacks(Spec spec) { 125 | this.runInvokables(this.collectInvokables(spec.getSuite(), Suite::getBeforeHandlers, true)); 126 | } 127 | 128 | 129 | private void runAfterEachCallbacks(Spec spec) { 130 | this.runInvokables(this.collectInvokables(spec.getSuite(), Suite::getAfterEachHandlers, false)); 131 | } 132 | 133 | 134 | private void runAfterCallbacks(Spec spec) { 135 | this.runInvokables(this.collectInvokables(spec.getSuite(), Suite::getAfterHandlers, false)); 136 | } 137 | 138 | 139 | private List collectInvokables(Suite suite, Function> method, boolean reverseOrder) { 140 | List> lists = new ArrayList<>(); 141 | Suite parent = suite; 142 | while (parent != null) { 143 | lists.add(new ArrayList<>(method.apply(parent))); 144 | parent = parent.getParent(); 145 | } 146 | 147 | if (reverseOrder) { 148 | Collections.reverse(lists); 149 | } 150 | 151 | List flatList = new ArrayList<>(); 152 | for (List list : lists) { 153 | flatList.addAll(list); 154 | } 155 | return flatList; 156 | } 157 | 158 | 159 | private void runInvokables(List invokables) { 160 | invokables.forEach(callback -> { 161 | try { 162 | callback.invoke(); 163 | } catch (Exception e) { 164 | throw new RuntimeException("An exception occurred while running invokable: " + e.getMessage(), e); 165 | } 166 | }); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/matchers/CollectionMatcherTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher.matchers; 2 | 3 | import com.mscharhag.oleaster.runner.OleasterRunner; 4 | import org.junit.runner.RunWith; 5 | 6 | import java.util.*; 7 | 8 | import static com.mscharhag.oleaster.matcher.TestUtil.expectAssertionError; 9 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 10 | 11 | @RunWith(OleasterRunner.class) 12 | public class CollectionMatcherTest {{ 13 | describe("CollectionMatcher test", () -> { 14 | final List list = new LinkedList<>(); 15 | list.add("one"); 16 | list.add("two"); 17 | 18 | final Set set = new HashSet<>(); 19 | set.add("one"); 20 | set.add("two"); 21 | 22 | describe("when toContain() is called", () -> { 23 | it("fails if the stored collection does not contain the expected value", () -> { 24 | expectAssertionError(() -> new CollectionMatcher(list).toContain("three"), 25 | "Expected '[one, two]' to contain 'three'"); 26 | expectAssertionError(() -> new CollectionMatcher(set).toContain("four"), 27 | "Expected '[one, two]' to contain 'four'"); 28 | }); 29 | 30 | it("fails if the stored collection is null", () -> { 31 | expectAssertionError(() -> new CollectionMatcher(null).toContain("one"), 32 | "Expected null to contain 'one'"); 33 | }); 34 | 35 | it("is ok if the stored collection contains the expected value", () -> { 36 | new CollectionMatcher(list).toContain("one"); 37 | new CollectionMatcher(set).toContain("two"); 38 | }); 39 | }); 40 | 41 | describe("when toNotContain() is called", () -> { 42 | it("fails if the stored collection does contain the expected value", () -> { 43 | expectAssertionError(() -> new CollectionMatcher(list).toNotContain("one"), 44 | "Expected '[one, two]' to not contain 'one'"); 45 | expectAssertionError(() -> new CollectionMatcher(set).toNotContain("one"), 46 | "Expected '[one, two]' to not contain 'one'"); 47 | }); 48 | 49 | it("fails if the stored collection is null", () -> { 50 | expectAssertionError(() -> new CollectionMatcher(null).toNotContain("one"), 51 | "Expected null to not contain 'one'"); 52 | }); 53 | 54 | it("is ok if the stored collection not contains the expected value", () -> { 55 | new CollectionMatcher(list).toNotContain("three"); 56 | new CollectionMatcher(set).toNotContain("three"); 57 | }); 58 | }); 59 | 60 | describe("when toBeEmpty() is called", () -> { 61 | it("fails if the stored collection is not empty", () -> { 62 | expectAssertionError(() -> new CollectionMatcher(list).toBeEmpty(), 63 | "Expected '[one, two]' to be empty"); 64 | expectAssertionError(() -> new CollectionMatcher(set).toBeEmpty(), 65 | "Expected '[one, two]' to be empty"); 66 | }); 67 | 68 | it("fails if the stored collection is null", () -> { 69 | expectAssertionError(() -> new CollectionMatcher(null).toBeEmpty(), 70 | "Expected null to be empty"); 71 | }); 72 | 73 | it("is ok if the stored collection is empty", () -> { 74 | new CollectionMatcher(new LinkedList()).toBeEmpty(); 75 | new CollectionMatcher(new HashSet()).toBeEmpty(); 76 | }); 77 | }); 78 | 79 | describe("when toNotBeEmpty() is called", () -> { 80 | it("fails if the stored collection is empty", () -> { 81 | expectAssertionError(() -> new CollectionMatcher(new LinkedList()).toNotBeEmpty(), 82 | "Expected '[]' to not be empty"); 83 | expectAssertionError(() -> new CollectionMatcher(new HashSet()).toNotBeEmpty(), 84 | "Expected '[]' to not be empty"); 85 | }); 86 | 87 | it("fails if the stored collection is null", () -> { 88 | expectAssertionError(() -> new CollectionMatcher(null).toNotBeEmpty(), 89 | "Expected null to not be empty"); 90 | }); 91 | 92 | it("is ok if the stored collection is not empty", () -> { 93 | new CollectionMatcher(list).toNotBeEmpty(); 94 | new CollectionMatcher(set).toNotBeEmpty(); 95 | }); 96 | }); 97 | 98 | describe("when toHaveSize() is called", () -> { 99 | it("fails if the stored collection does not have the provided size", () -> { 100 | expectAssertionError(() -> new CollectionMatcher(list).toHaveSize(1), 101 | "Expected '[one, two]' to have a size of 1, instead has a size of 2"); 102 | expectAssertionError(() -> new CollectionMatcher(set).toHaveSize(-1), 103 | "Expected '[one, two]' to have a size of -1, instead has a size of 2"); 104 | }); 105 | 106 | it("fails if the stored collection is null", () -> { 107 | expectAssertionError(() -> new CollectionMatcher(null).toHaveSize(1)); 108 | }); 109 | 110 | it("is ok if hte stored collection has the provided size", () -> { 111 | new CollectionMatcher(list).toHaveSize(2); 112 | new CollectionMatcher(set).toHaveSize(2); 113 | }); 114 | }); 115 | }); 116 | }} 117 | -------------------------------------------------------------------------------- /oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/matchers/MapMatcherTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.matcher.matchers; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.mscharhag.oleaster.runner.OleasterRunner; 7 | 8 | import org.junit.runner.RunWith; 9 | 10 | import static com.mscharhag.oleaster.matcher.TestUtil.expectAssertionError; 11 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 12 | 13 | @RunWith(OleasterRunner.class) 14 | public class MapMatcherTest {{ 15 | describe("MapMatcher test", () -> { 16 | 17 | final Map map = new HashMap<>(); 18 | map.put("one", 1); 19 | map.put("two", 2); 20 | 21 | describe("when toBeEmpty() is called", () -> { 22 | it("fails if the stored map is not empty", () -> { 23 | expectAssertionError(() -> new MapMatcher<>(map).toBeEmpty(), 24 | "Expected '{one=1, two=2}' to be empty"); 25 | }); 26 | 27 | it("fails if the stored map is null", () -> { 28 | expectAssertionError(() -> new MapMatcher<>(null).toBeEmpty(), 29 | "Expected null to be empty"); 30 | }); 31 | 32 | it("is ok if the stored map is empty", () -> { 33 | new MapMatcher<>(new HashMap()).toBeEmpty(); 34 | }); 35 | }); 36 | 37 | describe("when toNotBeEmpty() is called", () -> { 38 | it("fails if the stored map is empty", () -> { 39 | expectAssertionError(() -> new MapMatcher<>(new HashMap()).toNotBeEmpty(), 40 | "Expected '{}' to not be empty"); 41 | }); 42 | 43 | it("fails if the stored map is null", () -> { 44 | expectAssertionError(() -> new MapMatcher<>(null).toNotBeEmpty(), 45 | "Expected null to not be empty"); 46 | }); 47 | 48 | it("is ok if the stored map is not empty", () -> { 49 | new MapMatcher<>(map).toNotBeEmpty(); 50 | }); 51 | }); 52 | 53 | describe("when toContainKey() is called", () -> { 54 | it("fails if the stored map does not contain the expected key", () -> { 55 | expectAssertionError(() -> new MapMatcher<>(map).toContainKey("three"), 56 | "Expected '{one=1, two=2}' to contain key 'three'"); 57 | }); 58 | 59 | it("fails if the stored map is null", () -> { 60 | expectAssertionError(() -> new MapMatcher<>(null).toContainKey("one"), 61 | "Expected null to contain the key 'one'"); 62 | }); 63 | 64 | it("is ok if the stored map contains the expected key", () -> { 65 | new MapMatcher<>(map).toContainKey("one"); 66 | }); 67 | }); 68 | 69 | describe("when toNotContainKey() is called", () -> { 70 | it("fails if the stored map does not contain the expected key", () -> { 71 | expectAssertionError(() -> new MapMatcher<>(map).toNotContainKey("one"), 72 | "Expected '{one=1, two=2}' to not contain key 'one'"); 73 | }); 74 | 75 | it("fails if the stored map is null", () -> { 76 | expectAssertionError(() -> new MapMatcher<>(null).toNotContainKey("one"), 77 | "Expected null to not contain the key 'one'"); 78 | }); 79 | 80 | it("is ok if the stored map contains the expected key", () -> { 81 | new MapMatcher<>(map).toNotContainKey("three"); 82 | }); 83 | }); 84 | 85 | describe("when toContainValue() is called", () -> { 86 | it("fails if the stored map does not contain the expected value", () -> { 87 | expectAssertionError(() -> new MapMatcher<>(map).toContainValue(3), 88 | "Expected '{one=1, two=2}' to contain value '3'"); 89 | }); 90 | 91 | it("fails if the stored map is null", () -> { 92 | expectAssertionError(() -> new MapMatcher<>(null).toContainValue(1), 93 | "Expected null to contain the value '1'"); 94 | }); 95 | 96 | it("is ok if the stored map contains the expected value", () -> { 97 | new MapMatcher<>(map).toContainValue(2); 98 | }); 99 | }); 100 | 101 | describe("when toNotContainValue() is called", () -> { 102 | it("fails if the stored value does not contain the expected value", () -> { 103 | expectAssertionError(() -> new MapMatcher<>(map).toNotContainValue(1), 104 | "Expected '{one=1, two=2}' to not contain value '1'"); 105 | }); 106 | 107 | it("fails if the stored map is null", () -> { 108 | expectAssertionError(() -> new MapMatcher<>(null).toNotContainValue(1), 109 | "Expected null to not contain the value '1'"); 110 | }); 111 | 112 | it("is ok if the stored value contains the expected value", () -> { 113 | new MapMatcher<>(map).toNotContainValue(3); 114 | }); 115 | }); 116 | 117 | describe("when toHaveSize() is called", () -> { 118 | it("fails if the stored value does not have the provided size", () -> { 119 | expectAssertionError(() -> new MapMatcher<>(map).toHaveSize(3), 120 | "Expected '{one=1, two=2}' to have a size of 3, instead has a size of 2"); 121 | }); 122 | 123 | it("fails if the stored map is null", () -> { 124 | expectAssertionError(() -> new MapMatcher<>(null).toHaveSize(1), 125 | "Expected null to have size '1'"); 126 | }); 127 | 128 | it("is ok if the stored value does have the provided size", () -> { 129 | new MapMatcher<>(map).toHaveSize(2); 130 | }); 131 | }); 132 | 133 | }); 134 | }} 135 | -------------------------------------------------------------------------------- /oleaster-matcher/README.md: -------------------------------------------------------------------------------- 1 | Oleaster Matcher 2 | ===== 3 | 4 | Oleaster Matcher is a small library that provides [Jasmine-like Matchers](https://github.com/pivotal/jasmine/wiki/Matchers) 5 | for Java. Oleaster Matchers can be used as a replacement (or extension) for standard JUnit assertions. 6 | 7 | Expectations written with Oleaster Matchers look like this: 8 | 9 | ```java 10 | import static com.mscharhag.oleaster.matcher.Matchers.*; 11 | 12 | // same as JUnit's assertEquals(40 + 2, 42) 13 | expect(40 + 2).toEqual(42); 14 | 15 | // see if a String matches a regular expression 16 | expect("foobar").toMatch("fo{2}\\w+"); 17 | 18 | // test exceptions with Java 8 Lambdas 19 | expect(() -> { 20 | // code that throws IllegalArgumentException 21 | throw new IllegalArgumentException(); 22 | }).toThrow(IllegalArgumentException.class); 23 | ``` 24 | Oleaster Matchers do not depend on the Oleaster JUnit Runner. 25 | You can use Oleaster Matchers without using the Oleaster JUnit Runner. 26 | 27 | ## Getting started 28 | To use Oleaster Matchers you need `oleaster-matcher.jar` in your classpath. 29 | If you are using Maven you just have to add the following dependency: 30 | 31 | ```xml 32 | 33 | com.mscharhag.oleaster 34 | oleaster-matcher 35 | 0.2.0 36 | 37 | ``` 38 | 39 | Matcher objects can be created using one the various static `expect()` methods of the `Matchers` class. 40 | To improve readability it is recommended to statically import `Matchers.*` 41 | ```java 42 | import static com.mscharhag.oleaster.matcher.Matchers.*; 43 | ``` 44 | 45 | **Note:** You can find the source of all examples shown here in the `oleaster-examples` module 46 | (see: [MatcherExamplesTest.java](https://github.com/mscharhag/oleaster/blob/master/oleaster-examples/src/test/java/com/mscharhag/oleaster/examples/MatcherExamplesTest.java)) 47 | 48 | ## Primitive types 49 | 50 | ### Numbers 51 | The following samples show how numbers can be compared. 52 | 53 | ```java 54 | int value = 42; 55 | 56 | // check for exact value 57 | expect(value).toEqual(42); 58 | 59 | // check for greater/smaller values 60 | expect(value).toBeGreaterThan(41); 61 | expect(value).toBeSmallerThan(43); 62 | 63 | // check for range 64 | expect(value).toBeBetween(40, 45); 65 | 66 | // floating point number can often not be precisely represented by float/double values. 67 | // So make sure to compare them with an absolute error (delta) 68 | expect(42.0000001).toBeCloseTo(42); // uses default delta of 0.00001 69 | expect(42.0000001).toBeCloseTo(42, 0.000001); 70 | ``` 71 | For Numbers two different matcher classes are available: 72 | 73 | * [IntegerNumberMatcher](https://github.com/mscharhag/oleaster/blob/master/oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/IntegerNumberMatcher.java) 74 | is used to compare integer values (`int`, `long`, `short`, `byte`) 75 | * [FloatingPointNumberMatcher](https://github.com/mscharhag/oleaster/blob/master/oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/FloatingPointNumberMatcher.java) 76 | is used to compare floating point values (`float`, `double`) 77 | 78 | ### Boolean values 79 | The following samples show how boolean values can be compared. 80 | 81 | ```java 82 | boolean value = true; 83 | 84 | // check for a given parameter 85 | expect(value).toEqual(true); 86 | 87 | // check if true 88 | expect(value).toBeTrue(); 89 | 90 | // check if false 91 | value = false; 92 | expect(value).toBeFalse(); 93 | ``` 94 | 95 | For comparing boolean values [BooleanMatcher](https://github.com/mscharhag/oleaster/blob/master/oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/BooleanMatcher.java) will be used. 96 | 97 | ## Objects 98 | 99 | ```java 100 | Person person = new Person("John", "Smith"); 101 | 102 | // check for equality, delegates to Person.equals() 103 | expect(person).toEqual(new Person("John", "Smith")); 104 | 105 | // check if not null 106 | expect(person).toBeNotNull(); 107 | 108 | // check if null 109 | person = null; 110 | expect(person).toBeNull(); 111 | 112 | // check if instance of 113 | expect("Hello World!").toBeInstanceOf(String.class); 114 | ``` 115 | 116 | For comparing Objects [ObjectMatcher](https://github.com/mscharhag/oleaster/blob/master/oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/ObjectMatcher.java) will be used. 117 | 118 | ## Strings 119 | The following samples show how String values can be compared. 120 | 121 | ```java 122 | // check for exact value 123 | expect("foo").toEqual("foo"); 124 | 125 | // check string starting/ending 126 | expect("foobar").toStartWith("foo"); 127 | expect("foobar").toEndWith("bar"); 128 | 129 | // check if a String contains a given substring 130 | expect("foobar").toContain("oba"); 131 | 132 | // check if a String matches a regular expression 133 | expect("foobar").toMatch(Pattern.compile("fo+\\w*")); 134 | expect("foobar").toMatch("fo+\\w*"); 135 | ``` 136 | 137 | For comparing Strings [StringMatcher](https://github.com/mscharhag/oleaster/blob/master/oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/StringMatcher.java) will be used. 138 | 139 | ## Collections 140 | 141 | ``` 142 | // check if a collection contains a specific item 143 | expect(myList).toContain("my item"); 144 | expect(mySet).toNotContain(42); 145 | 146 | // check the size of a collection 147 | expect(myList).toBeEmpty(); 148 | expect(mySet).toHaveSize(15); 149 | ``` 150 | 151 | ### Maps 152 | 153 | ``` 154 | // check if a map contains a specific key 155 | expect(myMap).toContainKey("key"); 156 | 157 | // check if a map contains a specific value 158 | expect(myMap).toContainValue("value"); 159 | ``` 160 | 161 | ## Date and Time 162 | 163 | ``` 164 | // check if a date is before or after another date 165 | expect(date).toBeAfter(otherDate); 166 | expect(date).toBeBefore(otherDate); 167 | 168 | // check if a date is between two other dates 169 | expect(date).toBeBetween(firstDate, otherDate); 170 | 171 | // check if a date is close to another date 172 | expect(date).toBeCloseTo(otherDate, deltaInMillis ); 173 | ``` 174 | 175 | ## Exceptions 176 | To test exceptions you just have to wrap the code that throws the expected exception into a lambda expression and pass 177 | it to `expect()`. The lambda expression will be executed and thrown exceptions will be caught. 178 | The thrown exception can be checked with `toThrow()` as shown bellow: 179 | 180 | ```java 181 | // check if an exception is thrown 182 | expect(() -> { 183 | // code that throws IllegalArgumentException 184 | throw new IllegalArgumentException(); 185 | }).toThrow(IllegalArgumentException.class); 186 | 187 | // with exception message 188 | expect(() -> { 189 | // code that throws IllegalArgumentException 190 | throw new IllegalArgumentException("An argument is invalid"); 191 | }).toThrow(IllegalArgumentException.class, "An argument is invalid"); 192 | ``` 193 | 194 | For testing exceptions [ExceptionMatcher](https://github.com/mscharhag/oleaster/blob/master/oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/matchers/ExceptionMatcher.java) will be used. 195 | 196 | ## Licence 197 | 198 | This software is licensed under the Apache 2 license, quoted below. 199 | 200 | Copyright 2014 Michael Scharhag 201 | 202 | Licensed under the Apache License, Version 2.0 (the "License"); 203 | you may not use this file except in compliance with the License. 204 | You may obtain a copy of the License at 205 | 206 | http://www.apache.org/licenses/LICENSE-2.0 207 | 208 | Unless required by applicable law or agreed to in writing, software 209 | distributed under the License is distributed on an "AS IS" BASIS, 210 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 211 | See the License for the specific language governing permissions and 212 | limitations under the License. 213 | -------------------------------------------------------------------------------- /oleaster-runner/src/main/java/com/mscharhag/oleaster/runner/StaticRunnerSupport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.runner; 17 | 18 | import com.mscharhag.oleaster.runner.suite.SuiteBuilder; 19 | 20 | /** 21 | * {@code StaticRunnerSupport} gives access to a {@link com.mscharhag.oleaster.runner.suite.SuiteBuilder} 22 | * using static methods. 23 | *

Using {@code StaticRunnerSupport} is the preferred way to build a test suite. 24 | * For fluent access it is recommended to statically import the methods of this class. 25 | */ 26 | public class StaticRunnerSupport { 27 | 28 | private StaticRunnerSupport() { 29 | 30 | } 31 | 32 | private static SuiteBuilder suiteBuilder; 33 | 34 | static void setSuiteBuilder(SuiteBuilder sb) { 35 | suiteBuilder = sb; 36 | } 37 | 38 | /** 39 | * Creates a new test suite. 40 | *

Test suites can contain: 41 | *

    42 | *
  • specs (defined by using {@code it()}
  • 43 | *
  • other suites (defined by nesting {@code describe()} calls)
  • 44 | *
  • {@code beforeEach()} and {@code afterEach()} handlers.
  • 45 | *
46 | *

For example: 47 | *

{@code
 48 | 	 * describe("my test suite", () -> {
 49 | 	 *     ...
 50 | 	 * });
 51 | 	 * }
52 | * @param text A description of the test suite 53 | * @param block A code block that represents the test suite 54 | */ 55 | public static void describe(String text, Invokable block) { 56 | failIfNoSuiteBuilderAvailable("describe"); 57 | suiteBuilder.describe(text, block); 58 | } 59 | 60 | /** 61 | * Creates a focussed test suite. 62 | *

Test suites can contain: 63 | *

    64 | *
  • specs (defined by using {@code it()}
  • 65 | *
  • other suites (defined by nesting {@code describe()} calls)
  • 66 | *
  • {@code beforeEach()} and {@code afterEach()} handlers.
  • 67 | *
68 | *

For example: 69 | *

{@code
 70 | 	 * fdescribe("my test suite", () -> {
 71 | 	 *     ...
 72 | 	 * });
 73 | 	 * }
74 | * @param text A description of the test suite 75 | * @param block A code block that represents the test suite 76 | */ 77 | public static void fdescribe(String text, Invokable block) { 78 | failIfNoSuiteBuilderAvailable("fdescribe"); 79 | suiteBuilder.fdescribe(text, block); 80 | } 81 | 82 | /** 83 | * Creates a pending test suite. 84 | *

Test suites can contain: 85 | *

    86 | *
  • specs (defined by using {@code it()}
  • 87 | *
  • other suites (defined by nesting {@code describe()} calls)
  • 88 | *
  • {@code beforeEach()} and {@code afterEach()} handlers.
  • 89 | *
90 | *

For example: 91 | *

{@code
 92 | 	 * xdescribe("my test suite", () -> {
 93 | 	 * 		// This will not be executed
 94 | 	 *     ...
 95 | 	 * });
 96 | 	 * }
97 | * @param text A description of the test suite 98 | * @param block A code block that represents the test suite 99 | */ 100 | public static void xdescribe(String text, PendingInvokable block) { 101 | failIfNoSuiteBuilderAvailable("xdescribe"); 102 | suiteBuilder.xdescribe(text, block); 103 | } 104 | 105 | 106 | /** 107 | * Create a new spec. 108 | *

Specs are used to validate a specific test condition. 109 | *

For example: 110 | *

{@code
111 | 	 * it("returns a list containing one item", () -> {
112 | 	 *   assertEquals(1, getList().size());
113 | 	 * });
114 | 	 * }
115 | * @param text A description of the expected behavior 116 | * @param block A code block that implements the validation 117 | */ 118 | public static void it(String text, Invokable block) { 119 | failIfNoSuiteBuilderAvailable("it"); 120 | suiteBuilder.it(text, block); 121 | } 122 | 123 | /** 124 | * Create a new focussed spec. 125 | *

Focussed specs are used to temporarily only run these tests and disable the other specs. 126 | *

For example: 127 | *

{@code
128 | 	 * fit("returns a list containing one item", () -> {
129 | 	 *   assertEquals(1, getList().size());
130 | 	 * });
131 | 	 * }
132 | * @param text A description of the expected behavior 133 | * @param block A code block that implements the validation 134 | */ 135 | public static void fit(String text, Invokable block) { 136 | failIfNoSuiteBuilderAvailable("fit"); 137 | suiteBuilder.fit(text, block); 138 | } 139 | 140 | /** 141 | * Create a new pending spec. 142 | *

Pending specs are used to temporarily disable specs. 143 | *

For example: 144 | *

{@code
145 | 	 * it("returns a list containing one item");
146 | 	 * }
147 | * @param text A description of the expected behavior 148 | */ 149 | public static void it(String text) { 150 | failIfNoSuiteBuilderAvailable("it"); 151 | suiteBuilder.xit(text); 152 | } 153 | 154 | /** 155 | * Create a new pending spec. 156 | *

Pending specs are used to temporarily disable specs. 157 | *

For example: 158 | *

{@code
159 | 	 * xit("returns a list containing one item", () -> {
160 | 	 *   // This will not be executed.
161 | 	 *   assertEquals(1, getList().size());
162 | 	 * });
163 | 	 * }
164 | * @param text A description of the expected behavior 165 | * @param block A code block that implements the validation 166 | */ 167 | public static void xit(String text, Invokable block) { 168 | failIfNoSuiteBuilderAvailable("xit"); 169 | suiteBuilder.xit(text); 170 | } 171 | 172 | 173 | /** 174 | * Creates a new {@code beforeEach} handler for the surrounding test suite. 175 | *

For example: 176 | *

{@code
177 | 	 * beforeEach(() -> {
178 | 	 *   // this code runs before each spec
179 | 	 * });
180 | 	 * }
181 | * @param block A code block that is executed before every spec execution 182 | */ 183 | public static void beforeEach(Invokable block) { 184 | failIfNoSuiteBuilderAvailable("beforeEach"); 185 | suiteBuilder.beforeEach(block); 186 | } 187 | 188 | /** 189 | * Creates a new {@code before} handler for the surrounding test suite. 190 | *

For example: 191 | *

{@code
192 | 	 * before(() -> {
193 | 	 *   // this code runs once before first spec in suite
194 | 	 * });
195 | 	 * }
196 | * @param block A code block that is executed once before first spec in suite 197 | */ 198 | public static void before(Invokable block) { 199 | failIfNoSuiteBuilderAvailable("before"); 200 | suiteBuilder.before(block); 201 | } 202 | 203 | /** 204 | * Creates a new {@code after} handler for the surrounding test suite. 205 | *

For example: 206 | *

{@code
207 | 	 * after(() -> {
208 | 	 *   // this code runs once after last spec in suite
209 | 	 * });
210 | 	 * }
211 | * @param block A code block that is executed once after last spec in suite 212 | */ 213 | public static void after(Invokable block) { 214 | failIfNoSuiteBuilderAvailable("after"); 215 | suiteBuilder.after(block); 216 | } 217 | 218 | /** 219 | * Creates a new {@code afterEach} handler for the surrounding test suite. 220 | *

For example: 221 | *

{@code
222 | 	 * afterEach(() -> {
223 | 	 *   // this code runs after each spec
224 | 	 * });
225 | 	 * }
226 | * @param block A code block that is executed after every spec execution 227 | */ 228 | public static void afterEach(Invokable block) { 229 | failIfNoSuiteBuilderAvailable("afterEach"); 230 | suiteBuilder.afterEach(block); 231 | } 232 | 233 | 234 | private static void failIfNoSuiteBuilderAvailable(String methodName) { 235 | if (suiteBuilder == null) { 236 | throw new IllegalStateException(String.format("No suiteBuilder available, " + 237 | "maybe you called %s() in a location where it is not intended to be called?", methodName)); 238 | } 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /oleaster-runner/src/test/java/com/mscharhag/oleaster/runner/SuiteDefinitionEvaluatorTest.java: -------------------------------------------------------------------------------- 1 | package com.mscharhag.oleaster.runner; 2 | 3 | import com.mscharhag.oleaster.runner.suite.SuiteBuilder; 4 | import com.mscharhag.oleaster.runner.suite.Spec; 5 | import com.mscharhag.oleaster.runner.suite.Suite; 6 | import com.mscharhag.oleaster.runner.suite.SuiteDefinition; 7 | import com.mscharhag.oleaster.runner.suite.SuiteDefinitionEvaluator; 8 | import org.junit.runner.RunWith; 9 | 10 | import java.util.Arrays; 11 | import java.util.Optional; 12 | 13 | import static com.mscharhag.oleaster.runner.AssertUtil.assertEmptySuiteCollections; 14 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 15 | import static org.junit.Assert.*; 16 | 17 | @RunWith(OleasterRunner.class) 18 | public class SuiteDefinitionEvaluatorTest { 19 | 20 | private SuiteDefinitionEvaluator sde; 21 | private SuiteBuilder sb; 22 | private Suite suite, parent; 23 | private Invokable emptyInvokable = () -> {}; 24 | 25 | { 26 | describe("SuiteDefinitionEvaluator", () -> { 27 | 28 | beforeEach(() -> { 29 | sb = new SuiteBuilder(); 30 | StaticRunnerSupport.setSuiteBuilder(sb); 31 | sde = new SuiteDefinitionEvaluator(); 32 | }); 33 | 34 | describe("when a suite definition is evaluated", () -> { 35 | beforeEach(() -> { 36 | suite = sde.evaluate(new SuiteDefinition(null, "test description", emptyInvokable), sb); 37 | }); 38 | 39 | it("initializes the suite with empty collections", () -> { 40 | assertEmptySuiteCollections(suite); 41 | }); 42 | 43 | it("passes the description to the suite", () -> { 44 | assertEquals("test description", suite.getDescription()); 45 | }); 46 | }); 47 | 48 | describe("when the evaluated suite definition has a parent suite", () -> { 49 | beforeEach(() -> { 50 | parent = new Suite(null, "parent"); 51 | suite = sde.evaluate(new SuiteDefinition(parent, "suite definition", emptyInvokable), sb); 52 | }); 53 | 54 | it("passes the parent to the suite", () -> { 55 | assertEquals(parent, suite.getParent()); 56 | }); 57 | }); 58 | 59 | describe("when the suite definition contains specs", () -> { 60 | beforeEach(() -> { 61 | SuiteDefinition definition = new SuiteDefinition(null, "suite", () -> sb.it("spec", emptyInvokable)); 62 | suite = sde.evaluate(definition, sb); 63 | }); 64 | 65 | it("adds the specs to the suite", () -> { 66 | assertEquals(1, suite.getSpecs().size()); 67 | Spec spec = suite.getSpecs().get(0); 68 | assertEquals(suite, spec.getSuite()); 69 | assertEquals("spec", spec.getDescription()); 70 | }); 71 | }); 72 | 73 | describe("when the suite definition contains beforeEach handlers", () -> { 74 | beforeEach(() -> { 75 | SuiteDefinition definition = new SuiteDefinition(null, "test", () -> sb.beforeEach(emptyInvokable)); 76 | suite = sde.evaluate(definition, sb); 77 | }); 78 | 79 | it("adds the beforeEach handler to the suite", () -> { 80 | assertEquals(Arrays.asList(emptyInvokable), suite.getBeforeEachHandlers()); 81 | }); 82 | }); 83 | 84 | describe("when the suite definition contains afterEach handlers", () -> { 85 | beforeEach(() -> { 86 | SuiteDefinition definition = new SuiteDefinition(null, "test", () -> sb.afterEach(emptyInvokable)); 87 | suite = sde.evaluate(definition, sb); 88 | }); 89 | 90 | it("adds the afterEach handler to the suite", () -> { 91 | assertEquals(Arrays.asList(emptyInvokable), suite.getAfterEachHandlers()); 92 | }); 93 | }); 94 | 95 | describe("when the suite definition contains a child suite definition", () -> { 96 | beforeEach(() -> { 97 | SuiteDefinition suiteDefinition = new SuiteDefinition(null, "parent suite", () -> { 98 | sb.describe("child suite", emptyInvokable); 99 | }); 100 | suite = sde.evaluate(suiteDefinition, sb); 101 | }); 102 | 103 | it("adds the child suite to the suite", () -> { 104 | assertEquals(1, suite.getSuites().size()); 105 | Suite childSuite = suite.getSuites().get(0); 106 | assertEquals("child suite", childSuite.getDescription()); 107 | assertEmptySuiteCollections(childSuite); 108 | }); 109 | 110 | it("sets the parent of the child suite", () -> { 111 | Suite childSuite = suite.getSuites().get(0); 112 | assertEquals(suite, childSuite.getParent()); 113 | }); 114 | }); 115 | 116 | describe("when a suite is pending", () -> { 117 | final String DESC_ROOT = "root level"; 118 | final String DESC_ONE = "one"; 119 | final String DESC_TWO = "two"; 120 | final String DESC_TWO_ONE = "two > one"; 121 | beforeEach(() -> { 122 | suite = sde.evaluate(new SuiteDefinition(null, DESC_ROOT, () -> { 123 | xdescribe(DESC_ONE, () -> { 124 | it("hello", () -> { 125 | fail("I should be removed"); 126 | }); 127 | }); 128 | 129 | xdescribe(DESC_TWO, () -> { 130 | describe(DESC_TWO_ONE, () -> { 131 | it("hello", () -> { 132 | fail("I should be removed"); 133 | }); 134 | }); 135 | }); 136 | }), sb); 137 | }); 138 | 139 | it("should remove the it block of the it in DESC_ONE", () -> { 140 | final Suite descOneSuite = suite.getSuites().get(0); 141 | assertEquals(DESC_ONE, descOneSuite.getDescription()); 142 | assertEquals(Optional.empty(), descOneSuite.getSpecs().get(0).getBlock()); 143 | }); 144 | 145 | it("should remove the it block of the it which is deeper nested in DESC_TWO", () -> { 146 | final Suite descTwoSuite = suite.getSuites().get(1); 147 | assertEquals(DESC_TWO, descTwoSuite.getDescription()); 148 | 149 | final Suite deskTwoOneSuite = descTwoSuite.getSuites().get(0); 150 | assertEquals(DESC_TWO_ONE, deskTwoOneSuite.getDescription()); 151 | 152 | assertEquals(Optional.empty(), deskTwoOneSuite.getSpecs().get(0).getBlock()); 153 | }); 154 | }); 155 | 156 | describe("when a suite is focused", () -> { 157 | final String DESC_ONE = "desc-one"; 158 | final String DESC_TWO = "desc-two"; 159 | final String IT_ONE = "it-one"; 160 | final String IT_TWO = "it-two"; 161 | 162 | beforeEach(() -> { 163 | suite = sde.evaluate(new SuiteDefinition(null, "root", () -> { 164 | describe(DESC_ONE, () -> { 165 | it(IT_ONE, () -> fail("should not be found.")); 166 | }); 167 | 168 | fdescribe(DESC_TWO, () -> { 169 | it(IT_TWO, () -> assertTrue(true)); 170 | }); 171 | }), sb); 172 | }); 173 | 174 | it("should not find DESC_ONE nor IT_ONE", () -> { 175 | assertEquals(1, suite.getSuites().size()); 176 | assertFalse(DESC_ONE.equals(suite.getSuites().get(0).getDescription())); 177 | }); 178 | 179 | it("should find only DESC_TWO",() -> { 180 | assertTrue(DESC_TWO.equals(suite.getSuites().get(0).getDescription())); 181 | }); 182 | }); 183 | 184 | describe("with a more complex focused and pending suite collection", () -> { 185 | final String DESC_ONE = "d1"; 186 | final String IT_ONE = "d1-i1"; 187 | final String DESC_TWO = "d2"; 188 | final String IT_TWO = "d2-i1"; 189 | final String DESC_THREE = "d3"; 190 | final String IT_THREE = "d3-i1"; 191 | final String IT_FOUR = "d3-i2"; 192 | final String IT_FIVE = "d3-i3"; 193 | beforeEach(() -> { 194 | suite = sde.evaluate(new SuiteDefinition(null, "ROOT", () -> { 195 | fdescribe(DESC_ONE, () -> { 196 | it(IT_ONE, () -> assertTrue(true)); 197 | }); 198 | 199 | describe(DESC_TWO, () -> { 200 | it("does not run", () -> fail("does not run")); 201 | fit(IT_TWO, () -> assertTrue(true)); 202 | }); 203 | 204 | fdescribe(DESC_THREE, () -> { 205 | it(IT_THREE, () -> assertTrue(true)); 206 | xit(IT_FOUR, () -> fail("does not run")); 207 | it(IT_FIVE); 208 | }); 209 | }), sb); 210 | }); 211 | 212 | it("should run it's in the first focused describe", () -> { 213 | assertEquals(DESC_ONE, suite.getSuites().get(0).getDescription()); 214 | assertEquals(1, suite.getSuites().get(0).getSpecs().size()); 215 | assertEquals(IT_ONE, suite.getSuites().get(0).getSpecs().get(0).getDescription()); 216 | }); 217 | 218 | it("should not run DESC_TWO", () -> { 219 | assertEquals(2, suite.getSuites().size()); 220 | suite.getSuites().forEach(s -> assertNotEquals(DESC_TWO, s.getDescription())); 221 | }); 222 | 223 | it("should not run it xit's in DESC_THREE", () -> { 224 | final Suite d3 = suite.getSuites().get(1); 225 | assertEquals(DESC_THREE, d3.getDescription()); 226 | assertEquals(3, d3.getSpecs().size()); 227 | 228 | assertEquals(IT_THREE, d3.getSpecs().get(0).getDescription()); 229 | assertTrue(d3.getSpecs().get(0).getBlock().isPresent()); 230 | 231 | assertEquals(IT_FOUR, d3.getSpecs().get(1).getDescription()); 232 | assertFalse(d3.getSpecs().get(1).getBlock().isPresent()); 233 | }); 234 | 235 | it("should not run it's without bodies", () -> { 236 | final Suite d3 = suite.getSuites().get(1); 237 | 238 | assertEquals(IT_FIVE, d3.getSpecs().get(2).getDescription()); 239 | assertFalse(d3.getSpecs().get(2).getBlock().isPresent()); 240 | }); 241 | }); 242 | }); 243 | }} 244 | -------------------------------------------------------------------------------- /oleaster-matcher/src/main/java/com/mscharhag/oleaster/matcher/Matchers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Michael Scharhag 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.mscharhag.oleaster.matcher; 17 | 18 | import com.mscharhag.oleaster.matcher.matchers.*; 19 | import com.mscharhag.oleaster.matcher.matchers.datetime.DateMatcher; 20 | 21 | import java.util.Collection; 22 | import java.util.Date; 23 | import java.util.Map; 24 | 25 | /** 26 | * {@code Matchers} provides a set of static {@code expect()} methods that can (and should) be used to 27 | * obtain Matcher instances. 28 | *

The returned Matcher instances can be used to check test results. 29 | *

For example 30 | *

 31 |  *     expect(40 + 2).toEqual(42);
 32 |  *     expect(person).toBeNotNull();
 33 |  *     expect("foo").toStartWith("fo");
 34 |  * 
35 | *

For fluent access, it is recommended to statically import the methods of this class. 36 | */ 37 | public class Matchers { 38 | 39 | private Matchers() { 40 | // no instance needed 41 | } 42 | 43 | /** 44 | * Creates a new {@link com.mscharhag.oleaster.matcher.matchers.IntegerNumberMatcher} initialized with 45 | * the passed {@code value}. 46 | *

The returned matcher can be used to check {@code long} values. 47 | *

 48 | 	 *     expect(42l).toEqual(42);
 49 | 	 *     expect(42l).toBeGreaterThan(41);
 50 | 	 * 
51 | * @see com.mscharhag.oleaster.matcher.matchers.IntegerNumberMatcher 52 | * @param value the value that should be checked 53 | * @return a new {@code IntegerNumberMatcher} initialized with {@code value} 54 | */ 55 | public static IntegerNumberMatcher expect(long value) { 56 | return new IntegerNumberMatcher(value); 57 | } 58 | 59 | /** 60 | * Creates a new {@link com.mscharhag.oleaster.matcher.matchers.IntegerNumberMatcher} initialized with 61 | * the passed {@code value}. 62 | *

The returned matcher can be used to check {@code int} values. 63 | *

 64 | 	 *     expect(42).toEqual(42);
 65 | 	 *     expect(42).toBeGreaterThan(41);
 66 | 	 * 
67 | * @see com.mscharhag.oleaster.matcher.matchers.IntegerNumberMatcher 68 | * @param value the value that should be checked 69 | * @return a new {@code IntegerNumberMatcher} initialized with {@code value} 70 | */ 71 | public static IntegerNumberMatcher expect(int value) { 72 | return new IntegerNumberMatcher(value); 73 | } 74 | 75 | /** 76 | * Creates a new {@link com.mscharhag.oleaster.matcher.matchers.IntegerNumberMatcher} initialized with 77 | * the passed {@code value}. 78 | *

The returned matcher can be used to check {@code short} values. 79 | *

 80 | 	 *     expect((short) 42).toEqual(42);
 81 | 	 *     expect((short) 42).toBeGreaterThan(41);
 82 | 	 * 
83 | * @see com.mscharhag.oleaster.matcher.matchers.IntegerNumberMatcher 84 | * @param value the value that should be checked 85 | * @return a new {@code IntegerNumberMatcher} initialized with {@code value} 86 | */ 87 | public static IntegerNumberMatcher expect(short value) { 88 | return new IntegerNumberMatcher(value); 89 | } 90 | 91 | /** 92 | * Creates a new {@link com.mscharhag.oleaster.matcher.matchers.IntegerNumberMatcher} initialized with 93 | * the passed {@code value}. 94 | *

The returned matcher can be used to check {@code byte} values. 95 | *

 96 | 	 *     expect((byte) 42).toEqual(42);
 97 | 	 *     expect((byte) 42).toBeGreaterThan(41);
 98 | 	 * 
99 | * @see com.mscharhag.oleaster.matcher.matchers.IntegerNumberMatcher 100 | * @param value the value that should be checked 101 | * @return a new {@code IntegerNumberMatcher} initialized with {@code value} 102 | */ 103 | public static IntegerNumberMatcher expect(byte value) { 104 | return new IntegerNumberMatcher(value); 105 | } 106 | 107 | /** 108 | * Creates a new {@link com.mscharhag.oleaster.matcher.matchers.FloatingPointNumberMatcher} initialized with 109 | * the passed {@code value}. 110 | *

The returned matcher can be used to check {@code double} values. 111 | *

112 | 	 *     expect(42.0).toEqual(42.0);
113 | 	 *     expect(41.999 + 0.001).toBeCloseTo(42);
114 | 	 * 
115 | * @see com.mscharhag.oleaster.matcher.matchers.FloatingPointNumberMatcher 116 | * @param value the value that should be checked 117 | * @return a new {@code FloatingPointNumberMatcher} initialized with {@code value} 118 | */ 119 | public static FloatingPointNumberMatcher expect(double value) { 120 | return new FloatingPointNumberMatcher(value); 121 | } 122 | 123 | /** 124 | * Creates a new {@link com.mscharhag.oleaster.matcher.matchers.FloatingPointNumberMatcher} initialized with 125 | * the passed {@code value}. 126 | *

The returned matcher can be used to check {@code float} values. 127 | *

128 | 	 *     expect(42.0f).toEqual(42.0);
129 | 	 *     expect(41.999f + 0.001f).toBeCloseTo(42);
130 | 	 * 
131 | * @see com.mscharhag.oleaster.matcher.matchers.FloatingPointNumberMatcher 132 | * @param value the value that should be checked 133 | * @return a new {@code FloatingPointNumberMatcher} initialized with {@code value} 134 | */ 135 | public static FloatingPointNumberMatcher expect(float value) { 136 | return new FloatingPointNumberMatcher(value); 137 | } 138 | 139 | /** 140 | * Creates a new {@link com.mscharhag.oleaster.matcher.matchers.ExceptionMatcher} initialized with 141 | * the passed {@code CodeBlock}. 142 | *

The returned matcher can be used to check if the passed {@code CodeBlock} throw an exception. 143 | * {@link com.mscharhag.oleaster.matcher.matchers.ExceptionMatcher.CodeBlock} is a functional interface that can be 144 | * implemented using a Java 8 Lambda expression. 145 | *

Example: 146 | *

147 | 	 *     expect(() -> {
148 | 	 *         // code that should throw an IllegalArgumentException
149 | 	 *     }).toThrow(IllegalArgumentException.class);
150 | 	 * 
151 | * @see com.mscharhag.oleaster.matcher.matchers.ExceptionMatcher 152 | * @param block the code block that should throw an exception 153 | * @return a new {@code ExceptionMatcher} initialized with {@code block} 154 | */ 155 | public static ExceptionMatcher expect(ExceptionMatcher.CodeBlock block) { 156 | return new ExceptionMatcher(block); 157 | } 158 | 159 | /** 160 | * Creates a new {@link com.mscharhag.oleaster.matcher.matchers.BooleanMatcher} initialized with 161 | * the passed {@code value}. 162 | *

The returned matcher can be used to check {@code boolean} values. 163 | *

164 | 	 *     expect(true).toEqual(true);
165 | 	 *     expect(true).toBeTrue();
166 | 	 * 
167 | * @see com.mscharhag.oleaster.matcher.matchers.BooleanMatcher 168 | * @param value the value that should be checked 169 | * @return a new {@code BooleanMatcher} initialized with {@code value} 170 | */ 171 | public static BooleanMatcher expect(boolean value) { 172 | return new BooleanMatcher(value); 173 | } 174 | 175 | /** 176 | * Creates a new {@link com.mscharhag.oleaster.matcher.matchers.StringMatcher} initialized with 177 | * the passed {@code value}. 178 | *

The returned matcher can be used to check {@code String} values. 179 | *

180 | 	 *     expect("foo").toEqual("foo");
181 | 	 *     expect("foo").toStartWith("fo");
182 | 	 * 
183 | * @see com.mscharhag.oleaster.matcher.matchers.StringMatcher 184 | * @param value the value that should be checked 185 | * @return a new {@code StringMatcher} initialized with {@code value} 186 | */ 187 | public static StringMatcher expect(String value) { 188 | return new StringMatcher(value); 189 | } 190 | 191 | /** 192 | * Creates a new {@link com.mscharhag.oleaster.matcher.matchers.CollectionMatcher} initialized with 193 | * the passed {@code value}. 194 | *

The returned matcher can be used to check {@code Collection} values. 195 | *

196 | 	 *     expect(list).toContain("foo");
197 | 	 *     expect(list).toBeEmpty();
198 | 	 * 
199 | * @see com.mscharhag.oleaster.matcher.matchers.CollectionMatcher 200 | * @param value the value that should be checked 201 | * @return a new {@code CollectionMatcher} initialized with {@code value} 202 | */ 203 | public static CollectionMatcher expect(Collection value) { 204 | return new CollectionMatcher(value); 205 | } 206 | 207 | /** 208 | * Creates a new {@link com.mscharhag.oleaster.matcher.matchers.MapMatcher} initialized with 209 | * the passed {@code value}. 210 | *

The returned matcher can be used to check {@code Map} values. 211 | *

212 | 	 *     expect(map).toContainValue("foo");
213 | 	 *     expect(map).toHaveSize(3);
214 | 	 * 
215 | * @see com.mscharhag.oleaster.matcher.matchers.MapMatcher 216 | * @param value the value that should be checked 217 | * @return a new {@code MapMatcher} initialized with {@code value} 218 | */ 219 | public static MapMatcher expect(Map value) { 220 | return new MapMatcher<>(value); 221 | } 222 | 223 | /** 224 | * Creates a new {@link com.mscharhag.oleaster.matcher.matchers.ObjectMatcher} initialized with 225 | * the passed {@code value}. 226 | *

The returned matcher can be used to check {@code Object} values. 227 | *

228 | 	 *     expect(person).toEqual(new Person("john"));
229 | 	 *     expect(person).toBeNotNull();
230 | 	 * 
231 | * @see com.mscharhag.oleaster.matcher.matchers.ObjectMatcher 232 | * @param value the value that should be checked 233 | * @return a new {@code ObjectMatcher} initialized with {@code value} 234 | */ 235 | public static ObjectMatcher expect(Object value) { 236 | return new ObjectMatcher<>(value); 237 | } 238 | 239 | 240 | public static DateMatcher expect(Date date) { 241 | return new DateMatcher(date); 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /oleaster-runner/README.md: -------------------------------------------------------------------------------- 1 | Oleaster Runner 2 | ===== 3 | Oleaster Runner is a JUnit Runner that allows you to write JUnit tests like you would write Jasmine tests. 4 | 5 | ```java 6 | import org.junit.runner.RunWith; 7 | import com.mscharhag.oleaster.runner.OleasterRunner; 8 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 9 | 10 | @RunWith(OleasterRunner.class) 11 | public class RunnerIntroductionTest {{ 12 | describe("A suite", () -> { 13 | it("contains a spec with an expectation", () -> { 14 | // test code 15 | }); 16 | }); 17 | }} 18 | ``` 19 | 20 | ## Setup 21 | To use `OleasterRunner` you need to add `oleaster-runner.jar` to you classpath. Since `OleasterRunner` is a JUnit 22 | Runner you also need JUnit 4 in your classpath. 23 | If you are using Maven you just have to add the following dependencies to your `pom.xml`: 24 | ```xml 25 | 26 | 27 | com.mscharhag.oleaster 28 | oleaster-runner 29 | 0.2.0 30 | 31 | 32 | 33 | 34 | junit 35 | junit 36 | 4.11 37 | 38 | 39 | ``` 40 | `OleasterRunner` makes heavy use of Java 8 Lambdas, so make sure you configured Java 8 for you project. 41 | If you are using Maven you can configure Java 8 with the `maven-compiler-plugin` plugin: 42 | ```xml 43 | 44 | 45 | 46 | org.apache.maven.plugins 47 | maven-compiler-plugin 48 | 3.1 49 | 50 | 1.8 51 | 1.8 52 | 53 | 54 | 55 | 56 | ``` 57 | To improve readability it is recommended to statically import `StaticRunnerSupport.*` in your test classes. This gives 58 | you direct access to Oleaster's static `describe()`, `it()`, `beforeEach()` and `afterEach()` methods: 59 | ```java 60 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 61 | ``` 62 | 63 | ## Specs and Suites 64 | Specs and Suites are used to structure tests. 65 | 66 | A Spec is used to test the state of the code. Specs are created using the static `StaticRunnerSupport.it()` method. 67 | `it()` requires two method parameters: a `String` and an `Invokable` instance. The `String` is used to describe the 68 | purpose of the test. `Invokable` is a single method interface that is typically implemented using a Java 8 lambda 69 | expression. It implements the actual test. 70 | ```java 71 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.it; 72 | ... 73 | it("describes your test", () -> { 74 | // use assertions to check the expected result 75 | }); 76 | ``` 77 | 78 | Suites are used to describe your tests. A suite is created by using the static `StaticRunnerSupport.describe()` method. 79 | Like `it()`, `describe()` takes a `String` and an `Invokable` parameter. The `String` describes the suite. 80 | The `Invokable` implements the suite and (typically) contains specs. 81 | 82 | `describe()` takes a `String` and an `Invokable` instance as parameter. The String parameter is used to describe the purpose of your tests. 83 | `Invokable` is a single method interface that is typically implemented using a Java 8 lambda expression. It represents 84 | the piece of code that implements the suite and (typically) contains specs. 85 | 86 | ```java 87 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.describe; 88 | ... 89 | describe("describes your suite", () -> { 90 | // suite implementation 91 | }); 92 | ``` 93 | 94 | Specs and Suites are defined when an instance of the test class is created (e.g. in the constructor of test class). 95 | ```java 96 | import org.junit.runner.RunWith; 97 | import com.mscharhag.oleaster.runner.OleasterRunner; 98 | import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*; 99 | 100 | @RunWith(OleasterRunner.class) 101 | public class MyTest { 102 | public MyTest() { 103 | describe("A suite", () -> { 104 | it("contains a spec with an expectation", () -> { 105 | // test code 106 | }); 107 | }); 108 | } 109 | } 110 | ``` 111 | Instead of using the constructor it is also possible to use [initializer blocks](http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html). 112 | The following test does exactly the same as the test shown above (except that imports are skipped). 113 | ```java 114 | @RunWith(OleasterRunner.class) 115 | public class MyTest {{ 116 | describe("A suite", () -> { 117 | it("contains a spec with an expectation", () -> { 118 | // test code 119 | }); 120 | }); 121 | }} 122 | ``` 123 | Here the suite is defined in an initializer block (note the double braces). 124 | 125 | Suites are optional, so this works too: 126 | ```java 127 | @RunWith(OleasterRunner.class) 128 | public class MyTest {{ 129 | it("contains a spec with an expectation", () -> { 130 | // test code 131 | }); 132 | }} 133 | ``` 134 | 135 | Suites can be nested: 136 | ```java 137 | describe("a suite", () -> { 138 | describe("a nested suite", () -> { 139 | // suite implementation 140 | }); 141 | }); 142 | ``` 143 | 144 | ## Running code before/after specs 145 | With `beforeEach()` and `afterEach()` it is possible to run code before and after a spec is executed: 146 | ```java 147 | describe("beforeEach/afterEach example", () -> { 148 | beforeEach(() -> { 149 | // runs before every spec in this suite 150 | }); 151 | 152 | afterEach(() -> { 153 | // runs after every spec in this suite 154 | }); 155 | }); 156 | ``` 157 | If `beforeEach()` or `afterEach()` is used inside nested suites, `beforeEach()`/`afterEach()` blocks of the outer suite 158 | will run first. 159 | 160 | ## Running code before/after suites 161 | With `before()` and `after()` it is possible to run code once at first or at last within a suite respectively: 162 | ```java 163 | describe("before/after example", () -> { 164 | before(() -> { 165 | // runs before first spec in this suite 166 | }); 167 | 168 | after(() -> { 169 | // runs after last spec in this suite 170 | }); 171 | }); 172 | ``` 173 | If `before()` or `after()` is used inside nested suites, `before()`/`after()` blocks of the outer suite 174 | will run first. 175 | 176 | ## Focusing a test (run only a selection of tests) 177 | 178 | With `fdescribe()` and `fit()` it is possible to run a single test or a single suite: 179 | 180 | ```java 181 | describe("Test suite", () -> { 182 | it("test", () -> { 183 | // I will not run 184 | assertTrue(false); 185 | }); 186 | 187 | fit("focused test", () -> { 188 | // I will run 189 | assertTrue(true); 190 | }); 191 | 192 | fdescribe("focused suite", () -> { 193 | it("test", () -> { 194 | // I will be run 195 | assertTrue(true); 196 | }); 197 | }); 198 | 199 | describe("normal suite", () -> { 200 | it("test", () -> { 201 | // I will not run 202 | assertTrue(false); 203 | }); 204 | }); 205 | }); 206 | ``` 207 | 208 | ## Skipping a test 209 | 210 | With `xdescribe()` and `xit()` it is possible to disable a single test or single suite (mark as pending): 211 | 212 | ```java 213 | describe("Test suite", () -> { 214 | it("test", () -> { 215 | // I will run 216 | assertTrue(true); 217 | }); 218 | 219 | it("pending test"); 220 | 221 | xit("another pending test", () -> { 222 | // I will not run 223 | assertTrue(false); 224 | }); 225 | 226 | describe("normal suite", () -> { 227 | it("test", () -> { 228 | // I will run 229 | assertTrue(true); 230 | }); }); 231 | 232 | xdescribe("pending suite", () -> { 233 | it("test", () -> { 234 | // I will not run 235 | assertTrue(false); 236 | }); }); 237 | }); 238 | ``` 239 | 240 | ## Assertions 241 | 242 | Validating the result of a test can be done in various ways. 243 | Oleaster Matchers provide Jasmine-like Matchers for checking expected test results. However it is also possible to use 244 | standard JUnit assertions or additional libraries like [Hamcrest](https://github.com/hamcrest/JavaHamcrest). 245 | ```java 246 | it("shows different assertion styles", () -> { 247 | int value = 42; 248 | 249 | // standard JUnit 250 | assertEquals(42, value); 251 | 252 | // Hamcrest 253 | assertThat(value, equalTo(42)); 254 | 255 | // Jasmine / Oleaster 256 | expect(value).toEqual(42); 257 | }); 258 | ``` 259 | Have a look at the [Oleaster Matchers](https://github.com/mscharhag/oleaster/blob/master/oleaster-matcher/README.md) 260 | documentation for more information. 261 | 262 | ## Examples 263 | The following code shows an example of a more complete Oleaster test: 264 | 265 | ```java 266 | @RunWith(OleasterRunner.class) 267 | public class AudioPlayerExampleTest { 268 | private AudioPlayer player; 269 | { 270 | beforeEach(() -> { 271 | // create a new AudioPlayer instance before each test 272 | player = new AudioPlayer(); 273 | }); 274 | 275 | it("sets the initial player state to stopped", () -> { 276 | expect(player.getState()).toEqual(PlayerState.stopped); 277 | }); 278 | 279 | it("initializes the currently played track with null", () -> { 280 | expect(player.getCurrentlyPlayedTrack()).toBeNull(); 281 | }); 282 | 283 | describe("when a track is played", () -> { 284 | beforeEach(() -> { 285 | // play a track; this is the common precondition for all specs in this suite 286 | player.play(new Track("Run to the hills")); 287 | }); 288 | 289 | it("updates the player state to playing", () -> { 290 | expect(player.getState()).toEqual(PlayerState.playing); 291 | }); 292 | 293 | it("updates the currently played track", () -> { 294 | Track expectedTrack = new Track("Run to the hills"); 295 | expect(player.getCurrentlyPlayedTrack()).toEqual(expectedTrack); 296 | }); 297 | }); 298 | }} 299 | ``` 300 | You can find the source for this example in the `oleaster-examples` module (see: [AudioPlayerExampleTest.java](https://github.com/mscharhag/oleaster/blob/master/oleaster-examples/src/test/java/com/mscharhag/oleaster/examples/AudioPlayerExampleTest.java)). 301 | 302 | For more examples you can have a look at Oleaster tests which are written with Oleaster. 303 | See: 304 | 305 | * [Oleaster Runner tests](https://github.com/mscharhag/oleaster/tree/master/oleaster-runner/src/test/java/com/mscharhag/oleaster/runner) 306 | * [Oleaster Matcher tests](https://github.com/mscharhag/oleaster/tree/master/oleaster-matcher/src/test/java/com/mscharhag/oleaster/matcher/matchers) 307 | 308 | ## Licence 309 | 310 | This software is licensed under the Apache 2 license, quoted below. 311 | 312 | Copyright 2014 Michael Scharhag 313 | 314 | Licensed under the Apache License, Version 2.0 (the "License"); 315 | you may not use this file except in compliance with the License. 316 | You may obtain a copy of the License at 317 | 318 | http://www.apache.org/licenses/LICENSE-2.0 319 | 320 | Unless required by applicable law or agreed to in writing, software 321 | distributed under the License is distributed on an "AS IS" BASIS, 322 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 323 | See the License for the specific language governing permissions and 324 | limitations under the License. 325 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. --------------------------------------------------------------------------------