Open GuyPaddock opened 6 years ago
We have support for something similar via the Gherkin syntax - https://github.com/greghaskins/spectrum/blob/master/docs/GherkinDSL.md - but could not yet decide how to make it look for the RSpec style syntax.
Can you give an example of how you do it in RSpec, especially relating to the overloading of let
.
Note - this is essentially the same as #80
In our case, the request is a bit different than #80. The way we usually handle this in RSpec is by defining a shared example group:
class Cat
def make_sound
"Meow!"
end
end
class Dog
def make_sound
"Woof!"
end
end
shared_examples_for 'an animal' do
it 'makes a sound' do
expect(animal.make_sound).not_to be_nil
end
end
describe Cat do
let(:animal) { Cat.new }
it_behaves_like 'an animal'
end
describe Dog do
let(:animal) { Dog.new }
it_behaves_like 'an animal'
end
I was able to get a workable but verbose solution using a functional interface and lambda declared in the test. The lambdas are invoked from within the context of each overall test.
Here's a watered-down example (imagine that each lambda could actually have 5-10 tests, and the only things being passed-in are the suppliers for the values that vary from test to test):
@RunWith(Spectrum.class)
public class MyTest {
{
final Supplier<Object> someObject = let(() -> new Object());
final Supplier<MyObject> testObject = let(() -> new MyObject(object.get()));
final ComparisonSharedExample behavesLikeRegularEquality = (testMethod) -> {
it("returns the match", () -> {
assertThat(testMethod.get()).isSameAs(someObject.get());
});
};
final ComparisonSharedExample behavesLikeOppositeEquality = (testMethod) -> {
it("does not return the match", () -> {
assertThat(testMethod.get()).isNotSameAs(someObject.get());
});
};
describe("#compare1", () -> {
behavesLikeRegularEquality.run(
() -> {
return testObject.get().compare1();
});
});
describe("#compare2", () -> {
behavesLikeOppositeEquality.run(
() -> {
return testObject.get().compare2();
});
});
describe("#compare3", () -> {
behavesLikeRegularEquality.run(
() -> {
return testObject.get().compare3();
});
});
describe("#compare4", () -> {
behavesLikeOppositeEquality.run(
() -> {
return testObject.get().compare4();
});
});
}
interface ComparisonSharedExample {
void run(final Runnable testMethod);
}
}
This may just be something I'm overlooking in the docs -- or that could use an example -- but is there a way to do RSpec-style shared contexts and shared examples?
For example, I just wrote my first test using Spectrum, which looked like this:
Two of those scenarios are expected to throw the same exception with nearly the same error message. In RSpec, I'd abstract that out into a shared example group and then control what's provided using
let
. If shared example groups are out of the question, what would be the best practice when using Spectrum for this?