Skip to content

Commit

Permalink
Merge pull request #35 from peterklijn/master
Browse files Browse the repository at this point in the history
Focused and Pending specs + ObjectMatcher.toBeInstanceOf()
  • Loading branch information
mscharhag authored May 15, 2017
2 parents b4f04eb + e14c715 commit be1ccdd
Show file tree
Hide file tree
Showing 17 changed files with 571 additions and 54 deletions.
3 changes: 3 additions & 0 deletions oleaster-matcher/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ expect(person).toBeNotNull();
// check if null
person = null;
expect(person).toBeNull();

// check if instance of
expect("Hello World!").toBeInstanceOf(String.class);
```

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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
package com.mscharhag.oleaster.matcher.matchers;


import static com.mscharhag.oleaster.matcher.util.Expectations.expectTrue;
import static com.mscharhag.oleaster.matcher.util.Expectations.expectNotNull;
import static com.mscharhag.oleaster.matcher.util.Expectations.*;

/**
* Matcher class to validate Objects of type {@code T}.
Expand Down Expand Up @@ -60,6 +59,15 @@ public void toBeNotNull() {
expectTrue(this.value != null, "Expected null to be not null");
}

/**
* Checks if the stored value is an instance of the {@code expectedClass}
* <p>This method throws an {@code AssertionError} if the stored value is not of instance of {@code expectedClass}.
* @param expectedClass
*/
public void toBeInstanceOf(Class<?> expectedClass) {
expectTrue(expectedClass.isInstance(value), "Expected '%s' to be instance of '%s'", this.value, expectedClass.getName());
}

protected T getValue() {
return this.value;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.mscharhag.oleaster.matcher.matchers;

import com.mscharhag.oleaster.runner.OleasterRunner;

import org.junit.runner.RunWith;

import static com.mscharhag.oleaster.matcher.TestUtil.expectAssertionError;
import static com.mscharhag.oleaster.matcher.TestUtil.*;
import static com.mscharhag.oleaster.runner.StaticRunnerSupport.*;

@RunWith(OleasterRunner.class)
Expand Down Expand Up @@ -53,5 +54,44 @@ public class ObjectMatcherTest {{
new ObjectMatcher<>("foo").toBeNotNull();
});
});

describe("when toBeInstanceOf() is called", () -> {
it("fails if the value is not of instance of input", () -> {
expectAssertionError(() -> new ObjectMatcher<>("foo").toBeInstanceOf(Integer.class), "Expected 'foo' to be instance of 'java.lang.Integer'");
});

it("is ok if the value is instance of the expected class", () -> {
new ObjectMatcher<>("foo").toBeInstanceOf(String.class);

});

it("is ok if the value is of the same class", () -> {
final Animal john = new Animal("John");
new ObjectMatcher<>(john).toBeInstanceOf(Animal.class);
});

it("is ok if the value is a child of the parent class", () -> {
final Dog marie = new Dog("Marie");
new ObjectMatcher<>(marie).toBeInstanceOf(Animal.class);
});

it("is not ok if the value is a parent of the child class", () -> {
final Animal bo = new Animal("Bo");
expectAssertionError(() -> new ObjectMatcher<>(bo).toBeInstanceOf(Dog.class), "Expected '" + bo + "' to be instance of '" + Dog.class.getName() + "'");
});

});
});
}}
}
public static class Animal {
public final String name;
public Animal(final String name) {
this.name = name;
}
}
public static class Dog extends Animal {
public Dog(final String name) {
super(name);
}
}
}
64 changes: 64 additions & 0 deletions oleaster-runner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,70 @@ describe("before/after example", () -> {
If `before()` or `after()` is used inside nested suites, `before()`/`after()` blocks of the outer suite
will run first.

## Focusing a test (run only a selection of tests)

With `fdescribe()` and `fit()` it is possible to run a single test or a single suite:

```java
describe("Test suite", () -> {
it("test", () -> {
// I will not run
assertTrue(false);
});

fit("focused test", () -> {
// I will run
assertTrue(true);
});

fdescribe("focused suite", () -> {
it("test", () -> {
// I will be run
assertTrue(true);
});
});

describe("normal suite", () -> {
it("test", () -> {
// I will not run
assertTrue(false);
});
});
});
```

## Skipping a test

With `xdescribe()` and `xit()` it is possible to disable a single test or single suite (mark as pending):

```java
describe("Test suite", () -> {
it("test", () -> {
// I will run
assertTrue(true);
});

it("pending test");

xit("another pending test", () -> {
// I will not run
assertTrue(false);
});

describe("normal suite", () -> {
it("test", () -> {
// I will run
assertTrue(true);
}); });

xdescribe("pending suite", () -> {
it("test", () -> {
// I will not run
assertTrue(false);
}); });
});
```

## Assertions

Validating the result of a test can be done in various ways.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,14 @@ protected void runChild(Spec spec, RunNotifier notifier) {
runBeforeCallbacks(spec);
}

runBeforeEachCallbacks(spec);
runLeaf(spec, describeChild(spec), notifier);
runAfterEachCallbacks(spec);
if (spec.getBlock().isPresent()) {
runBeforeEachCallbacks(spec);
runLeaf(spec, describeChild(spec), notifier);
runAfterEachCallbacks(spec);
} else {
notifier.fireTestIgnored(describeChild(spec));
}


if (suiteHasNoSpecs || isLastSpec){
runAfterCallbacks(spec);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.mscharhag.oleaster.runner;

public interface PendingInvokable extends Invokable {}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,51 @@ public static void describe(String text, Invokable block) {
suiteBuilder.describe(text, block);
}

/**
* Creates a focussed test suite.
* <p>Test suites can contain:
* <ul>
* <li>specs (defined by using {@code it()}</li>
* <li>other suites (defined by nesting {@code describe()} calls)</li>
* <li>{@code beforeEach()} and {@code afterEach()} handlers.</li>
* </ul>
* <p>For example:
* <pre>{@code
* fdescribe("my test suite", () -> {
* ...
* });
* }</pre>
* @param text A description of the test suite
* @param block A code block that represents the test suite
*/
public static void fdescribe(String text, Invokable block) {
failIfNoSuiteBuilderAvailable("fdescribe");
suiteBuilder.fdescribe(text, block);
}

/**
* Creates a pending test suite.
* <p>Test suites can contain:
* <ul>
* <li>specs (defined by using {@code it()}</li>
* <li>other suites (defined by nesting {@code describe()} calls)</li>
* <li>{@code beforeEach()} and {@code afterEach()} handlers.</li>
* </ul>
* <p>For example:
* <pre>{@code
* xdescribe("my test suite", () -> {
* // This will not be executed
* ...
* });
* }</pre>
* @param text A description of the test suite
* @param block A code block that represents the test suite
*/
public static void xdescribe(String text, PendingInvokable block) {
failIfNoSuiteBuilderAvailable("xdescribe");
suiteBuilder.xdescribe(text, block);
}


/**
* Create a new spec.
Expand All @@ -75,6 +120,55 @@ public static void it(String text, Invokable block) {
suiteBuilder.it(text, block);
}

/**
* Create a new focussed spec.
* <p>Focussed specs are used to temporarily only run these tests and disable the other specs.
* <p>For example:
* <pre>{@code
* fit("returns a list containing one item", () -> {
* assertEquals(1, getList().size());
* });
* }</pre>
* @param text A description of the expected behavior
* @param block A code block that implements the validation
*/
public static void fit(String text, Invokable block) {
failIfNoSuiteBuilderAvailable("fit");
suiteBuilder.fit(text, block);
}

/**
* Create a new pending spec.
* <p>Pending specs are used to temporarily disable specs.
* <p>For example:
* <pre>{@code
* it("returns a list containing one item");
* }</pre>
* @param text A description of the expected behavior
*/
public static void it(String text) {
failIfNoSuiteBuilderAvailable("it");
suiteBuilder.xit(text);
}

/**
* Create a new pending spec.
* <p>Pending specs are used to temporarily disable specs.
* <p>For example:
* <pre>{@code
* xit("returns a list containing one item", () -> {
* // This will not be executed.
* assertEquals(1, getList().size());
* });
* }</pre>
* @param text A description of the expected behavior
* @param block A code block that implements the validation
*/
public static void xit(String text, Invokable block) {
failIfNoSuiteBuilderAvailable("xit");
suiteBuilder.xit(text);
}


/**
* Creates a new {@code beforeEach} handler for the surrounding test suite.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,19 @@
*/
package com.mscharhag.oleaster.runner.suite;

import java.util.Optional;

import com.mscharhag.oleaster.runner.Invokable;

import org.junit.runners.model.Statement;

public class Spec extends Statement {

private Suite suite;
private String description;
private Invokable block;
private Optional<Invokable> block;

public Spec(Suite suite, String description, Invokable block) {
public Spec(Suite suite, String description, Optional<Invokable> block) {
this.suite = suite;
this.description = description;
this.block = block;
Expand All @@ -48,6 +51,12 @@ public String getFullDescription() {

@Override
public void evaluate() throws Throwable {
block.invoke();
if (block.isPresent()) {
block.get().invoke();
}
}

public Optional<Invokable> getBlock() {
return block;
}
}
Loading

0 comments on commit be1ccdd

Please sign in to comment.