I am trying to use Geb+Spock to do web automation testing, but it keeps telling me :
Caught: java.lang.NoClassDefFoundError: spock/lang/Specification
Caused by: java.lang.ClassNotFoundException: spock.lang.Specification
And I think I have already added the things spock might need ...?
#Grapes([
#Grab('org.gebish:geb-core:1.1.1'),
#Grab('org.seleniumhq.selenium:selenium-chrome-driver:2.42.0'),
#Grab('org.seleniumhq.selenium:selenium-support:2.42.0'),
#Grab('org.gebish:geb-spock:1.1.1')
])
import geb.spock.GebSpec
import spock.lang.*
class GoogleSpec extends GebSpec{
def "Google search"() {
given:
to GooglePage
when:
searchBox.value == "Dogs"
and:
searchButton.click()
then:
at ResultPage
}
}
Well, maybe you also want to add dependencies to
Spock itself: org.spockframework:spock-core:1.0-groovy-2.4
Optionally, if you want to mock classes (in addition to interfaces) in Spock: cglib:cglib-nodep:3.2.4
Optionally, if you feel the urge to mock final classes (please don't, it is evil!) and classes without default constructors (that's fine) in Spock: org.objenesis:objenesis:2.2
I don't know anything about Gradle, but those I use in Maven.
P.S.: Maybe next time you want to use your favourite web search engine to look for sample projects or documentation first. You should find plenty.
Yup - you need spock-core not spock-parent or anything else.
org.spockframework:spock-core:1.1-groovy-2.4-rc-3
Related
I have made a java function genImage(List<String lines) which is located in class vis. I am trying to import it into my rascal code, but it won't work. This is the last of my efforts to import it:
#javaClass{visualization.vis}
java void genImage(list[str] lines);
The error I get:
Cannot link method visualization.vis because: visualization.vis.(io.usethesource.vallang.IValueFactory)
Advice: |http://tutor.rascal-mpl.org/Errors/Static/JavaMethodLink/JavaMethodLink.html%7C
The #javaClass tag must point to a fully qualified classname, including the package and the class. It seems it's the class you are missing, right?
I have written integration tests in Spock that I would like to reuse for load testing. I haven't had any luck with programmatically executing Spock tests. I need to run an entire spec as a single unit which will be executed concurrently to create load.
Previous posts on stack overflow on this topic are obsolete (I tried a bunch of them with no luck).
Example Spec:
class MySpec extends Specification {
def 'test'() {
expect: 1+1 == 2
}
}
I want to be able to run this in something like (executed, succeeded and failed are AtomicInteger):
executor.submit(() -> {
try {
executed.addAndGet(1);
Result result = mySpecInstance.run() // <-- what should this be.
if (result.wasSuccessful()) {
succeeded.addAndGet(1);
} else {
failed.addAndGet(1);
log.error("Failures encountered: {}", result.getFailures());
}
} catch (RuntimeException e) {
log.error("Exception when running runner!", e);
failed.addAndGet(1);
}});
I've tried the answer in this post which throws
Invalid test class 'my.package.MySpec':
1. No runnable methods]
I tried using the new EmbeddedSpecRunner().run(MySpec.class) which throws
groovy.lang.MissingMethodException: No signature of method: spock.util.EmbeddedSpecRunner.runClass() is applicable for argument types: (Class) values: [class my.package.MySpec]
Possible solutions: getClass(), metaClass(groovy.lang.Closure)
I am using JDK8 with Groovy 3.0.4 and spock-2.0-M3-groovy-3.0 (spock-junit4).
Update:
The answer from post works with Groovy-2.4, Spock-1.3 but not with Groovy-3.0 and Spock-2.0.
Thanks.
Your error did not occur because you used the wrong Spock version, by the way. You can use module spock-junit4 if you want to run the old JUnit 4 API. I just tried, the method works in Spock 1 and still in Spock 2, even though you maybe should upgrade to something that does not rely on an older API and a compatibility layer.
Your error message is simply caused by the fact that you copied & pasted code from the other answer without fixing it. The guy there wrote MySuperSpock.Class which causes the error because if must be MySuperSpock.class with a lower-case "C" or under Groovy simply MySuperSpock because the .class is optional there.
The error message even proves that you had JUnit 4 on the class path and everything was fine, otherwise the code importing JUnit 4 API classes would not have compiled in the first place. And the error message also explains what is wrong and suggests a solution:
Exception in thread "main" groovy.lang.MissingPropertyException: No such property: Class for class: de.scrum_master.testing.MyTest
Possible solutions: class
See? Class MyTest does not have any property called Class. And one possible solution (in this case even the correct one) is to use .class. This gives you a hint. BTW, the syntax MyTest.Class looks like an inner class reference or maybe a property reference to the compiler (to me too).
Update: I just took a closer look and noticed that the solution from the other question you said was working for Spock 1.3 actually compiles and runs, but the JUnit Core runner does not really run the tests. I tried with tests that print something. Furthermore, the result reports all tests as failed.
For simple cases you could use Spock's EmbeddedSpecRunner which is used internally to test Spock itself. Under Spock 1.x it should be enough to have JUnit 4 on the test class path, under Spock 2 which is based on JUnit 5 platform, you need to add these dependencies too because the embedded runner uses them:
<properties>
<version.junit>5.6.2</version.junit>
<version.junit-platform>1.6.2</version.junit-platform>
<version.groovy>3.0.4</version.groovy>
<version.spock>2.0-M3-groovy-3.0</version.spock>
</properties>
<!-- JUnit 5 Jupiter platform launcher for Spock EmbeddedSpecRunner -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>${version.junit-platform}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-testkit</artifactId>
<version>${version.junit-platform}</version>
<scope>test</scope>
</dependency>
Then you can run a test like this:
def spockRunner = new EmbeddedSpecRunner()
def spockResult = spockRunner.runClass(MyTest)
println "Tests run: " + spockResult.runCount
println "Tests ignored: " + spockResult.ignoreCount
println "Tests failed: " + spockResult.failureCount
BTW, the *Count getter methods are deprecated in Spock 2, but they still work. You can replace them by newer ones easily, I just wanted to post code which runs unchanged in both Spock versions 1.x and 2.x.
Update 2: If you want to run the same test e.g. 10x concurrently, each in its own thread, in Groovy a simple way to do that is:
(1..10).collect { Thread.start { new EmbeddedSpecRunner().runClass(MyTest) } }*.join()
Or maybe a bit easier to read with a few line breaks:
(1..10)
.collect {
Thread.start { new EmbeddedSpecRunner().runClass(MyTest) }
}
*.join()
I am assuming that you are familiar with collect (similar to map for Java streams) and the star-dot operator *. (call a method on each item in an iterable).
Below is the domain:
package com.test
class Person{
String name
static mappedBy= [friends:'none']
static hasMany=[friends:Person]
}
It works well for normal cases, but When I tried to test it by mocking using #Mock annotation in spock for save, got exception below:
| org.grails.datastore.mapping.model.IllegalMappingException:
Non-existent mapping property [none] specified for property [friends] in class [com.test.Person]
at org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy.establishRelationshipForCollection(GormMappingConfigurationStrategy.java:364)
at org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy.getPersistentProperties(GormMappingConfigurationStrategy.java:206)
at org.grails.datastore.mapping.model.AbstractPersistentEntity.initialize(AbstractPersistentEntity.java:87)
at org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy.getOrCreateAssociatedEntity(GormMappingConfigurationStrategy.java:675)
at org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy.establishDomainClassRelationship(GormMappingConfigurationStrategy.java:632)
at org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy.getPersistentProperties(GormMappingConfigurationStrategy.java:214)
at org.grails.datastore.mapping.model.AbstractPersistentEntity.initialize(AbstractPersistentEntity.java:87)
at org.grails.datastore.mapping.model.AbstractMappingContext.initializePersistentEntity(AbstractMappingContext.java:250)
at org.grails.datastore.mapping.model.AbstractMappingContext.initialize(AbstractMappingContext.java:239)
at grails.test.mixin.domain.DomainClassUnitTestMixin.initializeMappingContext(DomainClassUnitTestMixin.groovy:150)
at grails.test.mixin.domain.DomainClassUnitTestMixin.mockDomains(DomainClassUnitTestMixin.groovy:144)
at org.spockframework.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:138)
at org.spockframework.runtime.extension.builtin.JUnitFixtureMethodsExtension$FixtureType$FixtureMethodInterceptor.intercept(JUnitFixtureMethodsExtension.java:145)
at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:84)
at org.spockframework.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:138)
at org.spockframework.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:138)
at org.spockframework.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:138)
Below is the test case:
import grails.test.mixin.Mock
import grails.test.mixin.TestFor
import spock.lang.Specification
#TestFor(PersonController)
#Mock([Person])
class PersonControllerSpec extends Specification{
def "test save person"(){
given:"some person request parameters set for person"
params.putAll([name:'test234', friends:[], action:'save', controller:'person'])
when:"perosn.save is called"
controller.save()
then:"it must create person object"
Person.count() == 1
}
}
Any idea what could be done in this case?
This issue is fixed after grails 2.5.1: https://github.com/grails/grails-core/issues/669
I solved the issue in our project by upgrading to Grails 2.5.5, and updating the used hibernate4 plugin to version hibernate4:5.0.0.RELEASE.
Though there already exists a Jira for same issue which is jira.grails.org/browse/GRAILS-11285
I am able to find out a work around by changing the version of grails-datastore jar as we were getting exception below
Non-existent mapping property [none] specified for property [friends]
in GormMappingConfigurationStrategy.java which is under grails-datastore-core jar.
Hence, after upgrading the version to 3.1.5 from 3.0.6 and just to be safe added a check for test environment as well like below
if (Environment.getCurrentEnvironment() == Environment.TEST) {
compile 'org.grails:grails-datastore-core:3.1.5.RELEASE'
}
Now, the jar would only be added for test environment and we can continue with our test cases.
Cheers!!!
package com.scheduler.process;
public class Process {
public enum state {
NOT_SUBMITTED, SUBMITTED, BLOCKED, READY, RUNNING, COMPLETED
}
private state currentState;
public state getCurrentState() {
return currentState;
}
public void setCurrentState(state currentState) {
this.currentState = currentState;
}
}
package com.scheduler.machine;
import com.scheduler.process.Process;
import com.scheduler.process.Process.state;
public class Machine {
com.scheduler.process.Process p = new com.scheduler.process.Process();
state s = state.READY; //fails if I don't also explicitly import Process.state
p.setCurrentState(s); //says I need a declarator id after 's'... this is wrong.
p.setCurrentState(state.READY);
}
Modified the example to try and direct to the issue. I cannot change the state on this code. Eclipse suggests importing Process.state like I had on my previous example, but this doesn't work either. This allows state s = state.READY but the call to p.setCurrentState(s); fails as does p.setCurrentState(state.READY);
Problem continued.... Following Oleg's suggestions I tried more permutations:
package com.scheduler.machine;
import com.scheduler.process.Process;
import com.scheduler.process.Process.*;
public class Machine {
com.scheduler.process.Process p = new com.scheduler.process.Process();
public state s = Process.state.READY;
p.setCurrentState(s);
p.setCurrentState(state.READY);
}
Okay. It's clear now that I'm a candidate for lobotomy.
package com.scheduler.machine;
import com.scheduler.process.Process;
import com.scheduler.process.Process.state;
public class Machine {
public void doStuff(){
com.scheduler.process.Process p = new com.scheduler.process.Process();
state s = state.READY; //fails if I don't also explicitly import Process.state
p.setCurrentState(s); //says I need a declarator id after 's'... this is wrong.
p.setCurrentState(state.READY);
}
}
I needed to have a method in the class--but we're still missing something (probably obvious) here. When I go via the command line and run javac on the Machine class AFTER compiling Process, I still get the following error:
mseil#context:/media/MULTIMEDIA/Scratch/Scratch/src/com/scheduler/machine$ javac Machine.java
Machine.java:3: package com.scheduler.process does not exist
import com.scheduler.process.Process;
^
So I guess the question now becomes, what idiot thing am I missing that is preventing me from compiling this by hand that eclipse is doing for me behind the scene?
======
Problem solved here:
Java generics code compiles in eclipse but not in command line
This has just worked for me:
Download latest Eclipse
Create new project
Create two packages com.scheduler.process and com.scheduler.machine
Create class Process in package com.scheduler.process and class Machine in com.scheduler.machine and copy their contents from your post modifying them to conform to Java language syntax, like this:
Everything compiles right away.
------ to answer the previous version of the question ------
To answer the question as it is right now: you need to either
import com.scheduler.process.Process.status or import com.scheduler.process.Process.* and refer to status as just status
or
import com.scheduler.process.* or import com.scheduler.process.Process and refer to status as Process.status
------ to answer the original version of the question ------
You can't import classes that are not inside some package. You just can't. It is a compile time error to import a type from the unnamed package.
You don't need to import anything if your classes are in the same package, or if all of your classes are packageless.
If Process class was inside some package it would be possible to import just its status inner class: import a.b.c.Process.status would work just fine.
All your Windows/Linux migration issues don't have anything to do with Java and exceptions that you see. import Process.state; will produce exception on any OS because you can't import classes that don't belong to any package.
Eclipse doesn't use the Sun JDK by default. I would assume that you are using Eclipse's built in compiler as Sun's JDK and the OpenJDK are almost identical.
Java code compiles and runs exact the same on Windows and Linux most of the time (unless you use a few of the platform specific operations)
I suspect you are not building the code the same way and when you compile Machine, the Process class has not been compiled.
I suggest you use a standard build system like maven or ant and it will build the same everywhere. Failing that run Eclipse on Linux or just the same .class you use on windows as they don't need to be re-compiled in any case.
BTW: You don't need to import Process.state as it not used and its in the same package (so you wouldn't need to if you did)
I'm going through the "Getting Started with Grails" ebook and have hit a wall with chapter 4 (Validation) on page 38 (actual page 50). Here is the code:
Oh, there might be a typo in the code in the book, though it didn't affect the behavior or error messages I got, on the following line:
def code = badField?.codes.find {
it == 'race.startDate.validator.invalid'
}
As I said, it doesn't affect the main execution, but was just curious if I'm right or if this is something in Groovy I haven't run across yet. I put what I thought it should be below.
package racetrack
import groovy.util.GroovyTestCase
class RaceIntegrationTests extends GroovyTestCase {
void testRaceDatesBeforeToday() {
def lastWeek = new Date() - 7
def race = new Race(startDate:lastWeek)
assertFalse "Validation should not succeed", race.validate()
// It should have errors after validation fails
assertTrue "There should be errors", race.hasErrors()
println "\nErrors:"
println race.errors ?: "no errors found"
def badField = race.errors.getFieldError('startDate')
println "\nBadField:"
println badField ?: "startDate wasn't a bad field"
assertNotNull "Expecting to find an error on the startDate field", badField
def code = badField ?: codes.find {
it == 'race.startDate.validator.invalid'
}
println "\nCode:"
println code ?:"the custom validator for startDate wasn't found"
assertNotNull "startDate field should be the culprit", code
}
}
where, when running "grails test-app", I get the following:
Error executing script TestApp: java.lang.RuntimeException: Could not load class in test type 'integration'
java.lang.RuntimeException: Could not load class in test type 'integration'
at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:391)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
at gant.Gant.withBuildListeners(Gant.groovy:427)
at gant.Gant.this$2$withBuildListeners(Gant.groovy)
at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
at gant.Gant.dispatch(Gant.groovy:415)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.executeTargets(Gant.groovy:590)
at gant.Gant.executeTargets(Gant.groovy:589)
Caused by: java.lang.RuntimeException: Could not load class in test type 'integration'
at _GrailsTest_groovy$_run_closure4.doCall(_GrailsTest_groovy:261)
at _GrailsTest_groovy$_run_closure4.call(_GrailsTest_groovy)
at _GrailsTest_groovy$_run_closure2.doCall(_GrailsTest_groovy:228)
at _GrailsTest_groovy$_run_closure1_closure21.doCall(_GrailsTest_groovy:187)
at _GrailsTest_groovy$_run_closure1.doCall(_GrailsTest_groovy:174)
at TestApp$_run_closure1.doCall(TestApp.groovy:82)
at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
... 10 more
The book is using Grails 1.2.x and I'm using 1.3.x and already noticed some discrepancies between the versions (nothing unsurmountable), so it could be something like that, but I can't seem to figure it out. Being new to Groovy and Grails isn't helping! :-D
Can anyone explain what I can do to get past this?
I just got this error, my cause was that my test class was in the wrong package.
I could not find a way to get a clearer description of the problem, even running with the --stacktrace option showed no more information.
It seems like this error can be caused by different compilation issues, perhaps?
I had the same problem (although I'm using Grails 2.3.4) - I fixed it by explicitly including
import racetrack.Race
instead of
package racetrack
Interestingly, after I tried this I commented it out and everything still worked - until I did a grails clean. Then it failed again. Suspect something not quite 100% in the grails / groovy auto compilation stuff.
I hit this problem with Grails 2.4.2. The cause was I had a test file named FooTest, but the class was named FooTest**s**.
Running grails test-app --stacktrace helped find the offending class.
First of all, I don't think you need this to be an 'integration' test. Place it under the 'src/test/unit/...' directory structure. Second of all, if you want to test the Grails 'validate()' method that is going to be injected by the Grails framework based on your 'constraints' block, you must make the test extend 'GrailsUnitTest' and call 'mockDomain(Race)' on the first line of your unit test method. If that is unclear, ping me and I'll post code but my guess is your book has a pretty good example of this. Here is some 'free hand' code that might fix it...
class RaceTests extends GrailsUnitTest {
void testRaceDatesBeforeToday() {
mockDomain(Race)
...
please make sure that your package name is correct, the above error means that its trying to run the test but since the package name is specified wrong its not able to find the file with that particular package name.