What is the idiomatic way to run a Specification over multitple implementations with Spock? - spock

Let's say I have a Joiner interface:
interface Joiner {
String join(List<String> l);
}
And two implementations of it:
class Java8Joiner implements Joiner {
#Override String join(List<String> l) { String.join("", l); }
}
class GroovyJoiner implements Joiner {
#Override String join(List<String> l) { l.join('') }
}
What is the best way to check that theses two implementation, or more, pass the same tests?
Basically, I want to run all the tests defined by JoinerSpecification with a Java8Joiner, then a GroovyJoiner, and so on...
class JoinerSpecification extends Specification {
#Subject
final def joiner = // Joiner instance here
def "Joining #list -> #expectedString"(List<String> list, String expectedString) {
expect:
joiner.join(list) == expectedString
where:
list | expectedString
[] | ''
['a'] | 'a'
['a', 'b'] | 'ab'
}
}
It is perfectly fine to refactor JoinerSpecification if needed.
My primary goals are:
Maintainable test code (with as little boilerplate as possible)
Clear error messages (which test of which implementation is failing)
Easy to run from the IDE
Edit 1 (15/06/2015)
Reworded my question & added some details to make it clearer.

Opal's proposal is interesting but is impractical. Not being able to use then blocks is a showstopper.
Lets try a self-answer using another approach. Since the goal is to execute the same specification on several implementations of the same interface, why not try to use good old inheritance ?
abstract class AbstractJoinerSpec extends Specification {
abstract Joiner getSubject()
#Unroll
def "Joining #list -> #expectedString"(List<String> list, String expectedString) {
given:
def joiner = getSubject()
expect:
joiner.join(list) == expectedString
where:
list | expectedString
[] | ''
['a'] | 'a'
['a', 'b'] | 'ab'
}
}
class Java8JoinerSpec extends AbstractJoinerSpec {
#Override
Joiner getSubject() { new Java8Joiner() }
}
class GroovyJoinerSpec extends AbstractJoinerSpec {
#Override
Joiner getSubject() { new Java8Joiner() }
}
Basically, the only abstract method is getSubject and all the inherited test cases are executed by Spock (I have not been able to find this feature in the documentation but it does work).
Pros
It only requires creating a tiny class for each implementation and the specification code remains clean.
The full power of Spock can be used
Error messages and reports are clear (you know which test failed for which implementation)
Cons
Running a given test for a given implementation from the IDE is not easy. You have to copy/paste the test case into the non abstract specification or remove the abstract modifiers and implement the getSubject method.
I thing the trade-off acceptable since you don't manually run/debug an implementation that often. Keeping the code clean, and having meaningful report worth this inconvenience.

What would be very useful here is comparison chaining but, as far as I know it's not implemented in groovy, see here. Since Subject purpose according to the docs is pure informational I've come up with the following ideas:
#Grab('org.spockframework:spock-core:0.7-groovy-2.0')
#Grab('cglib:cglib-nodep:3.1')
import spock.lang.*
class Test extends Specification {
def 'attempt 1'() {
given:
def joiners = [new GroovyJoiner(), new Java8Joiner()]
expect:
joiners.every { it.join(list) == expectedString }
where:
list | expectedString
[] | ''
['a'] | 'a'
['a', 'b'] | 'ab'
}
def 'attempt 2'() {
given:
def gJoiner = new GroovyJoiner()
def jJoiner = new Java8Joiner()
expect:
[gJoiner.join(list), jJoiner.join(list), expectedString].toSet().size() == 1
where:
list | expectedString
[] | ''
['a'] | 'a'
['a', 'b'] | 'ab'
}
}
interface Joiner {
String join(List<String> l);
}
class Java8Joiner implements Joiner {
#Override String join(List<String> l) { String.join("", l); }
}
class GroovyJoiner implements Joiner {
#Override String join(List<String> l) { l.join('') }
}
In the attempt 1 I'm just checking if every element on the list is equal to expectedString. It looks nice however on error it's not verbose enough. Any element may fail and there's no trace which one.
The attempt 2 method makes use of Set. Since all the results should be equal there'll be only one element left in the collection. In prints verbose info on test failure.
What also comes to my head is guava's ComparisonChain but no idea if it would be useful as well as it's another project dependency.

Unfortunately, there is no way to create a cartesian product of two lists declaratively in Spock. You have to define your own Iterable that will provide the values for your variables.
There is a more readable (using Spock tabular data definition) way to define the data, if you are willing to sacrifice terseness for readability. Let me know if that interests you. Otherwise here is a solution that lets you define everything declaratively, without duplication, but you lose the nice tabular definitions of Spock.
If your implementation is stateless, i.e. it does not keep state, you can get away with using #Shared instances of Joiner:
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll
interface Joiner {
String join(List<String> l);
}
class Java8Joiner implements Joiner {
#Override
String join(List<String> l) { String.join("", l); }
}
class GroovyJoiner implements Joiner {
#Override
String join(List<String> l) { l.join('') }
}
class S1Spec extends Specification {
#Shared
Joiner java8Joiner = new Java8Joiner()
#Shared
Joiner groovyJoiner = new GroovyJoiner()
List<Map> transpose(Map<List> mapOfLists) {
def listOfMaps = [].withDefault { [:] }
mapOfLists.each { k, values ->
[values].flatten().eachWithIndex { value, index ->
listOfMaps[index][k] = value
}
}
listOfMaps
}
Iterable distribute(List<Joiner> joiners, Map<String, List> data) {
def varsForEachIteration = transpose(data)
new Iterable() {
#Override
Iterator iterator() {
[joiners, varsForEachIteration].combinations().iterator()
}
}
}
#Unroll
def "Joining with #joiner #list -> #expectedString"() {
expect:
joiner.join(list) == expectedString
where:
[joiner, data] << distribute([java8Joiner, groovyJoiner], [
list : [[], ['a'], ['a', 'b']],
expectedString: ['', 'a', 'ab']
])
and:
list = data.list
expectedString = data.expectedString
}
}

Related

Unit test case for Domain class ( testing constraints) - Grails

I am actually new in the world of Grails. I am trying to write a test case for domain class which is having some constraints . I am getting a Null pointer exception on my object when i am trying to run my unit test. On debugging I got to know that there is something fishy with my toString method which is causing the object to set as Null. How should I move ahead ? Any help is highly appreciated.
Here is my domain class:
#MultiTenant
class OrderCharge {
static scaffold = [
exclude: ['tenantId'],
]
static belongsTo = [
order: SalesOrder
]
MiscOrderCharges miscOrderCharges
Date lastUpdated
double quantity
double price
SapInvoiceRecord sapInvoice
static constraints = {
order(nullable: true)
quantity(min:1d)
miscOrderCharges()
sapInvoice(nullable: true)
}
String toString(){
def pattern = "\$##,###.00"
def currency = new DecimalFormat(pattern)
String rate = currency.format(miscOrderCharges.price)
return "$miscOrderCharges x$quantity"
}
}
Here is my Unit test case:
import grails.test.mixin.TestFor
import spock.lang.Unroll
import spock.lang.Specification
#TestFor(OrderCharge)
//#TestMixin(GroovyPageUnitTestMixin)
class ChargeSpec extends Specification {
def setup() {
mockForConstraintsTests(
OrderCharge, [
new OrderCharge(order: Mock(SalesOrder),
miscOrderCharges: Mock(MiscOrderCharges),
quantity: 1.0,
price:20.0
/*, sapInvoice: Mock(SapInvoiceRecord) */
)
]
)
}
void validateConstraints(obj, field, error) {
def validated = obj.validate()
if (error && error != 'valid') {
assert !validated
assert obj.errors[field]
assert error == obj.errors[field]
} else {
assert !obj.errors[field]
}
}
#Unroll("test inventory all constraints #field is #error")
def "test Charge all constraints"() {
given:
def obj = new OrderCharge("$field": val)
expect:
validateConstraints(obj, field, error)
where:
error |field |val
'nullable' |'orderCharge' |null
'nullable' |'sapInvoice' |null
'min' |'quantity' |-1
'min' |'price' |0
}
}
Thanks in advance.
The only thing that jumps out at me is your return in the toString().
return "$miscOrderCharges x$quantity"
You're using gStrings there. It's my understanding that individual variables can be referred to using simple $ notation, as in the format $somevariable, whereas expressions are in the format ${expression}.
In your statement x$quantity seems like a typo. Did you mean to multiply them as an expression like below?
return "${miscOrderCharges * quantity}"
See http://groovy.jmiguel.eu/groovy.codehaus.org/Strings+and+GString.html for more information.

XText cross-reference to an non-DSL resource

Please consider this minimal Xtext grammar.
Model:
"As a" stackeholder=Stakeholder "I want" want=Want;
Stakeholder:
'client' | 'developer' | 'manager';
Want:
'everything' | 'cookies' | 'fame';
Now what I need to do, is to move the definition of stakeholders (let's forget about want) to SOME external data source. This "external data source" might be a CSV file, might be a DB or maybe a web service. But I it is highly unlikely to be some Xtext file or to come with an EMF model. But still I want to cross-reference it just like you can cross-reference java types in your DSL.
Issues like manual parsing and caching (for performance sake) aside: is this even doable?
I've dug a little into the topic of scopes and resource providers but everything I found required the external source to be part of at least another DSL.
I'd be very happy about a rough outline what would be needed to be done.
Sorry it took me so long to respond. I tried Christians suggestion, was not very satisfied and than priorities shifted. Now I'll have another go at the problem and in order to document for others (and to clear my head) I'll write down what I did so far since it was not all that straight forward and required a fair amount of experimentation.
I will not post full classes but only the relevant parts. Feel free to ask for more detail if you need it.
My Syntax-Definition now looks like this:
Model:
stakeholders+=StakeholderDecl*
requirements+=Requirement*;
Requirement:
'As a' stakeholder=[Stakeholder] 'I want' want=('everything' | 'cookies' | 'results')
;
StakeholderDecl returns Stakeholder :
'Stakeholder' Stakeholder
;
Stakeholder:
name=ID
;
Let it be noted that everything below needed to to be done in the .ui package.
First I created StakeholdersProvider.xtend:
class StakeholdersProvider extends AbstractResourceDescription {
// this is the dummy for an "external source". Just raw data.
val nameList = newArrayList( "buddy", "boss" )
val cache = nameList.map[it.toDescription]
private val uri = org.eclipse.emf.common.util.URI.createPlatformResourceURI("neverland", true)
def public List<IEObjectDescription> loadAdditionalStakeholders() {
cache
}
def private IEObjectDescription toDescription(String name) {
ExternalFactoryImpl.init()
val ExternalFactory factory = new ExternalFactoryImpl()
val Stakeholder obj = factory.createStakeholder as StakeholderImpl
obj.setName(name)
new StakeholderDescription(name, obj, uri)
}
. . .
override getURI() {
uri
}
def public boolean isProvided( EObject object ) {
if( object.eClass.classifierID != ExternalPackageImpl.STAKEHOLDER ) {
false
}
else {
val stakeholder = object as Stakeholder
nameList.exists[it == stakeholder.name]
}
}
}
note that the provider is also a resourceDescription and its uri of course is nonsense.
With this provider I wrote a ScopeWrapper.xtend :
class ScopeWrapper implements IScope {
private var IScope scope;
private var StakeholdersProvider provider
new( IScope scopeParam, StakeholdersProvider providerParam ) {
scope=scopeParam
provider = providerParam
}
override getAllElements() {
val elements = scope.allElements.toList
val ret = provider.loadAdditionalStakeholders()
ret.addAll(elements)
ret
}
override getSingleElement(QualifiedName name) {
allElements.filter[it.name == name].head
}
. . .
}
and ResourceDescriptionWrapper.xtend
class ResourceDescriptionsWrapper implements IResourceDescriptions {
private StakeholdersProvider provider;
private IResourceDescriptions descriptions;
new(IResourceDescriptions descriptionsParam, StakeholdersProvider providerParam) {
descriptions = descriptionsParam
provider = providerParam
}
override getAllResourceDescriptions() {
val resources = descriptions.allResourceDescriptions.toList
resources.add(provider)
resources
}
override getResourceDescription(URI uri) {
if( uri == provider.URI ) provider
else descriptions.getResourceDescription(uri)
}
override getExportedObjects() {
val descriptions = descriptions.exportedObjects.toList
descriptions.addAll(provider.exportedObjects)
descriptions
}
. . . some overrides for getExportedObjects-functions
}
all of this is wired together MyGlobalScopeProvider.xtend
class MyGlobalScopeProvider extends TypesAwareDefaultGlobalScopeProvider {
val provider = new StakeholdersProvider()
override getScope(Resource context, EReference reference, Predicate<IEObjectDescription> filter) {
val scope = super.getScope(context, reference, filter)
return new ScopeWrapper(scope, provider)
}
override public IResourceDescriptions getResourceDescriptions(Resource resource) {
val superDescr = super.getResourceDescriptions(resource)
return new ResourceDescriptionsWrapper(superDescr, provider)
}
}
which is registered in MyDslUiModule.java
public Class<? extends IGlobalScopeProvider> bindIGlobalScopeProvider() {
return MyGlobalScopeProvider.class;
}
So far so good. I now get boss and buddy suggested as stakeholders. However when I use one of those 2 I get an error in the editor complaining about a dangling reference and an error logging in the console that a stakeholder cannot be exported as the target is not contained in a resource. Figuring those 2 might are related I tried to fix the error logging, created MyresourceDescriptionStrategy.xtend
class MyResourcesDescriptionStrategy extends DefaultResourceDescriptionStrategy {
val provider = new StakeholdersProvider()
override isResolvedAndExternal(EObject from, EObject to) {
if (provider.isProvided(to)) {
// The object is a stakeholder that was originally provided by
// our StakeholdersProvider. So we mark it as resolved.
true
} else {
super.isResolvedAndExternal(from, to)
}
}
}
and also wire it in the UiModule:
public Class<? extends IDefaultResourceDescriptionStrategy> bindDefaultResourceDescriptionStrategy() {
return MyResourcesDescriptionStrategy.class;
}
This fixes the logging error but the "dangling reference" problem remains. I searched for solutions for this and the most prominent result suggests that defining a IResourceServiceProvider would have been the best way to solve my problem in the first place.
I'll spend a bit more time on the current approach and than try it with a ResourceProvider.
EDIT: I got the "dangling reference" problem fixed. The loadAdditionalStakeholders() function in StakeholdersProvider.xtend now looks like this:
override loadAdditionalStakeholders() {
val injector = Guice.createInjector(new ExternalRuntimeModule());
val rs = injector.getInstance(ResourceSet)
val resource = rs.createResource(uri)
nameList.map[it.toDescription(resource)]
}
def private IEObjectDescription toDescription(String name, Resource resource) {
ExternalFactoryImpl.init()
val ExternalFactory factory = new ExternalFactoryImpl()
val Stakeholder obj = factory.createStakeholder as StakeholderImpl
obj.setName(name)
// not sure why or how but when adding the obj to the resource, the
// the resource will be set in obj . . . thus no more dangling ref
resource.contents += obj
new StakeholderDescription(name, obj, uri)
}

GORM bidirectional One-to-Many

I'm trying to create a bidirectional one-to-many relationship between Foo and Bar domains in GORM.
Here's what I have so far:
class Bar {
static belongsTo = [foo: Foo]
}
class Foo {
Set bars = []
static hasMany = [bars: Bar]
}
The problem that I'm having is when I go to use the relationship methods, they don't seem to behave the way that I think they should. For example, you would think a statement like "foo.bars.add(bar)" would also set the foo field on the bar argument. But when I call "bar.foo.id" I'm told that the foo field is null. I can fix that problem if I use "bar.foo = foo" instead of "foo.bars.add(bar)". Unfortunately, when I call "foo.bars.size()" it tells me that it is 0.
To get a clearer picture of what I'm talking about, here are my tests:
def testFoo() {
def foo = new Foo()
def bar = new Bar()
foo.bars.add(bar)
println "foo.bars.size() = ${foo.bars.size()}"
println "bar.id = ${bar.id}"
for(def xbar : foo.bars) {
println "bar.id = ${xbar.id}"
}
println "foo.id = ${foo.id}"
println "bar.foo.id = ${bar?.foo?.id}" // <- is null
}
def testBar() {
def foo = new Foo()
def bar = new Bar()
bar.foo = foo
println "foo.bars.size() = ${foo.bars.size()}" // <- is 0
println "bar.id = ${bar.id}"
for(def xbar : foo.bars) {
println "bar.id = ${xbar.id}"
}
println "foo.id = ${foo.id}"
println "bar.foo.id = ${bar?.foo?.id}"
}
What am I doing wrong?
Note: I'm running this through an integration test. I've also found that "foo.addToBars(bar)" works the way that I think "foo.bars.add(bar)" and "bar.foo = foo" should work.
Update Here's a quick hack I did that does what I want (using Hibernate and JPA):
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import stuff.Foo;
public class MyList<Bar> extends LinkedList {
private Foo foo;
public MyList(Foo foo) {
this.foo = foo;
}
#Override
public boolean add(Object obj) {
boolean result = super.add(obj);
try {
Method barMethod = obj.getClass().getDeclaredMethod("setFoo", Foo.class);
barMethod.invoke(obj, foo);
}
catch(NoSuchMethodException noSuchMethod) {
noSuchMethod.printStackTrace();
}
catch(InvocationTargetException invocationTarget) {
invocationTarget.printStackTrace();
}
catch(IllegalAccessException illegalAccess) {
illegalAccess.printStackTrace();
}
return result;
}
}
If you read the documentation, you'll learn that, as you found out but are still questioning, the correct way to add items to a collection so they are persisted correctly is to use the addTo* methods.
So in your case, when you said that using addToBars worked, that's the right way to do this. That said, there are some performance hits you take with that. Another way is to do:
bar.foo = foo
bar.save()
The downside is that foo will not contain bar in its existing Set. You'd have to pull it from the database again. It's a bit of a give and take and you just use the best method for your situation.

How can I access alternate labels in ANTLR4 while generically traversing a parse tree?

How can I access alternate labels in ANTLR4 while generically traversing a parse tree? Or alternatively, is there any way of replicating the functionality of the ^ operator of ANTLR3, as that would do the trick.
I'm trying to write an AST pretty printer for any ANTLR4 grammar adhering to a simple methodology (like naming productions with alternate labels). I'd like to be able to pretty print a term like 3 + 5 as (int_expression (plus (int_literal 3) (int_literal 5))), or something similar, given a grammar like the following:
int_expression
: int_expression '+' int_expression # plus
| int_expression '-' int_expression # minus
| raw_int # int_literal
;
raw_int
: Int
;
Int : [0-9]+ ;
I am unable to effectively give names to the plus and minus productions, because pulling them out into their own production causes the tool to complain that the rules are mutually left-recursive. If I can't pull them out, how can I give these productions names?
Note 1: I was able to get rid of the + argument methodologically by putting "good" terminals (e.g., the Int above) in special productions (productions starting with a special prefix, like raw_). Then I could print only those terminals whose parent productions are named "raw_..." and elide all others. This worked great for getting rid of +, while keeping 3 and 5 in the output. This could be done with a ! in ANTLR3.
Note 2: I understand that I could write a specialized pretty printer or use actions for each production of a given language, but I'd like to use ANTLR4 to parse and generate ASTs for a variety of languages, and it seems like I should be able to write such a simple pretty printer generically. Said another way, I only care about getting ASTs, and I'd rather not have to encumber each grammar with a tailored pretty printer just to get an AST. Perhaps I should just go back to ANTLR3?
I suggest implementing the pretty printer as a listener implementation with a nested visitor class to get the names of the various context objects.
private MyParser parser; // you'll have to assign this field
private StringBuilder builder = new StringBuilder();
#Override
public void enterEveryRule(#NotNull ParserRuleContext ctx) {
if (!builder.isEmpty()) {
builder.append(' ');
}
builder.append('(');
}
#Override
public void visitTerminalNode(#NotNull TerminalNode node) {
// TODO: print node text to builder
}
#Override
public void visitErrorNode(#NotNull TerminalNode node) {
// TODO: print node text to builder
}
#Override
public void exitEveryRule(#NotNull ParserRuleContext ctx) {
builder.append(')');
}
protected String getContextName(#NotNull ParserRuleContext ctx) {
return new ContextNameVisitor().visit(ctx);
}
protected class ContextNameVisitor extends MyParserBaseVisitor<String> {
#Override
public String visitChildren() {
return parser.getRuleNames()[ctx.getRuleIndex()];
}
#Override
public String visitPlus(#NotNull PlusContext ctx) {
return "plus";
}
#Override
public String visitMinus(#NotNull MinusContext ctx) {
return "minus";
}
#Override
public String visitInt_literal(#NotNull MinusContext ctx) {
return "int_literal";
}
}
The API doesn't contain a method to access the alternate labels.
However there is a workaround. ANTLR4 uses the alternate labels to generate java class names and those java classes can be accessed at run time.
For example: to access alternate labels in ANTLR4 while generically traversing a parse tree (with a listener) you can use the following function:
// Return the embedded alternate label between
// "$" and "Context" from the class name
String getCtxName(ParserRuleContext ctx) {
String str = ctx.getClass().getName();
str = str.substring(str.indexOf("$")+1,str.lastIndexOf("Context"));
str = str.toLowerCase();
return str;
}
Example use:
#Override
public void exitEveryRule(ParserRuleContext ctx) {
System.out.println(getCtxName(ctx));
}

How do I compare two objects to see if they are the same instance, in Dart?

Say I have a class that has many instance variables,. I want to overload the == operator (and hashCode) so I can use instances as keys in maps.
class Foo {
int a;
int b;
SomeClass c;
SomeOtherClass d;
// etc.
bool operator==(Foo other) {
// Long calculation involving a, b, c, d etc.
}
}
The comparison calculation may be expensive, so I want to check if other is the same instance as this before making that calculation.
How do I invoke the == operator provided by the Object class to do this ?
You're looking for "identical", which will check if 2 instances are the same.
identical(this, other);
A more detailed example?
class Person {
String ssn;
String name;
Person(this.ssn, this.name);
// Define that two persons are equal if their SSNs are equal
bool operator ==(Person other) {
return (other.ssn == ssn);
}
}
main() {
var bob = new Person('111', 'Bob');
var robert = new Person('111', 'Robert');
print(bob == robert); // true
print(identical(bob, robert)); // false, because these are two different instances
}
You can use identical(this, other).
For completeness, this is a supplemental answer to the existing answers.
If some class Foo does not override ==, then the default implementation is to return whether they are the same object. The documentation states:
The default behavior for all Objects is to return true if and only if this object and other are the same object.
That's my way how I compare deep 2 Objects they're not the same:
class Foo{
String uid;
bool isActiv;
Foo(this.uid, this.isActiv){}
Map<String, dynamic> toJson() => _$FooToJson(this);
}
Foo A = Foo("alpha", true);
Foo B = Foo("alpha", true);
print(A.toJson().toString() == B.toJson().toString()); // true
B.uid = "beta";
print(A.toJson().toString() == B.toJson().toString()); // false
On a different yet similar note, in cases where the framework calls to check the equality among the objects e.g. in case of list.toSet() to get the unique elements from a list, identical(this, other) may not be a choice. That time the class must override the == operator and the hasCode() methods.
However for this case another way could be to use the equatable package. This saves a lot of boiler plate code and is especially handy when you have lot of model classes.
You can use Equatable library
class Foo extends EquatableMixin{
int? a;
int? b;
SomeClass? c;
SomeOtherClass? d;
Foo(this.a,this.b,this.c,this.d);
// this does the job, it overrides the hashcode and equals operator
// give all properties to this `props`
#override
List<Object> get props => [a,b,c,d];
}
class SomeOtherClass with EquatableMixin{
String name;
SomeOtherClass(this.name);
#override
List<Object> get props => [name];
}
class SomeClass with EquatableMixin{
String name;
SomeClass(this.name);
#override
List<Object> get props => [name];
}
Foo foo =
Foo(1,2,SomeOtherClass("roger"),SomeOtherClassObject("mack"));
Foo foo2 =
Foo(1,2,SomeOtherClass("roger"),SomeOtherClassObject("mack"));
print(foo == foo2) // prints true
So, we don't need to manually override == and hashcode() methods
the library will do that.
Note : the inner objects (SomeClass and SomeOtherClass) should also use EquatableMixin, we can extends this or use as a mixin too

Resources