I have a grails 3.1.x project with lots of controllers and I use spock for testing the controllers.
I use a command pattern for my controllers so each action takes a command object.
An example for such a controller :
class PlaygroundController {
public Object pg(PgCO pgco) {
String s = null
if (pgco.one) {
s = pgco.one
}
if (pgco.two) {
s = pgco.two
}
render view: 'pg', model: [resultat: s]
}
}
I have a simple spock test case:
void "pg"() {
given:
PgCO pgCO = new PgCO()
pgCO.one = 'TEST'
when:
controller.pg(pgCO)
then:
view == '/playground/pg'
model
model.resultat == 'TEST'
}
This test runs fine, but when i run a jacocoTestReport it shows that my coverage is way below 50% , it's fine that it's not fully covered since I'm only covering one branch.
But the report contains loads of "missed instructions" on methods that I have no source code for.. specially there is a shadow pg() method that doesn't take any parameters. Grails injects this method, but I will never call that method from my tests since I use the command object version of the same method. this method but also a lot of other methods coming from grails controller framework.
Isn't there anyw ay to tell jacoco that it's only the "source code" that needs to be checked for coverage ?
I've tried specifying exact source dirs, but this doesn't help
Here's an image of the coverage report:
coverage report
I have a daily simple project just enabling the jacoco plugin, and running latest jacoco :
jacoco {
toolVersion = "0.7.5.201505241946"
}
Have anyone else a solution to this ?
Related
Whenever I am trying to run the tagged test cases in jenkins, they are getting skipped with the message
WARN org.testng.internal.Utils - The test method 'testRunner.TestRunner.feature' will be skipped since its data provider 'features' returned an empty array or iterator.
but the same test cases are getting executed and passed in my local machine. I have integrated cucumber with maven and testNG
Below is my test runner file
#CucumberOptions(features = { "src/test/java/com/test_Cases_FeatureFiles" },
glue = {"stepDefs"},
plugin = { "pretty","html:target/cucumber-html-report","com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:" },
monochrome = true,
tags = "#FileDownload_Tests")
public class TestRunner extends AbstractTestNGCucumberTests {
}
Please suggest a way out for this issue.
I'm tryting to run our Cucumber JVM tests by few threads in parallel.
I'm using standart TastNG approach to do it (via suite XML file)
My xml file is:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="BDD" parallel="methods" thread-count="3" data-provider-thread-count="3">
<test name="BDD">
<classes>
<class name="com.tests.bdd.SimpleBDDTests"></class>
</classes>
</test>
</suite>
My test class is:
#CucumberOptions(features = "src/test/java/com/tests/bdd/simpleFeatures")
public class SimpleBDDTests {
private TestNGCucumberRunner tcr;
#BeforeClass(alwaysRun = true)
public void beforeClass() throws Exception {
tcr = new TestNGCucumberRunner(this.getClass());
}
#AfterClass(alwaysRun = true)
public void afterClass() {
tcr.finish();
}
#Test(dataProvider = "features")
public void feature(CucumberFeatureWrapper cucumberFeature) {
tcr.runCucumber(cucumberFeature.getCucumberFeature());
}
#DataProvider(parallel = true)
public Object[][] features() {
return tcr.provideFeatures();
}}
My feature files are like:
Feature: First test
#sanity
Scenario: First simple test
Given Base check step
I have 4 feature files, which are defines the same scenarios with only one step - Given Base check step
When these features are executed one by one, it works fine, but when i try to run them in parallel, everything gets broken.
Almost all of these featres marked as failed with the following exception:
A scoping block is already in progress
java.lang.IllegalStateException: A scoping block is already in progress
at cucumber.runtime.java.guice.impl.SequentialScenarioScope.checkState(SequentialScenarioScope.java:64)
at cucumber.runtime.java.guice.impl.SequentialScenarioScope.enterScope(SequentialScenarioScope.java:52)
at cucumber.runtime.java.guice.impl.GuiceFactory.start(GuiceFactory.java:34)
at cucumber.runtime.java.JavaBackend.buildWorld(JavaBackend.java:123)
at cucumber.runtime.Runtime.buildBackendWorlds(Runtime.java:141)
at cucumber.runtime.model.CucumberScenario.run(CucumberScenario.java:38)
at cucumber.runtime.model.CucumberFeature.run(CucumberFeature.java:165)
at cucumber.api.testng.TestNGCucumberRunner.runCucumber(TestNGCucumberRunner.java:63)
I understand that it might be happen because of multi-thread calls to the same step - Given Base check step
So my question is how can i fix that? How can i run these tests in parallel?
PS: I know that it should be possible to do it by JUnit + Maven surefire plugin, but it is not applicable for current project, we need to achieve that goal by TestNG.
Thanks.
I use Spock to test an action of a controller as below:
code in controller:
def milestoneChange() {
Milestones selectedMilestone = dataQueryService.getMilestone(params.id)
Tasks[] tasksList = dataQueryService.getTasksList(params.id)
List enumerateNameList = dataQueryService.getEnumerateNameList()
render(template: 'milestoneSummary', model: [selectedMilestone: selectedMilestone, tasksList: tasksList, enumerateNameList: enumerateNameList, selectedMilestoneID: params.id])
}
code in test:
#TestFor(MilestonesMgtController)
class MilestonesMgtControllerSpec extends Specification {
void "change the milestone"() {
when:
views['/milestonesMgt/_milestoneSummary.gsp'] = "test"
controller.params.id = 'Late Stage Review'
controller.milestoneChange()
then:
controller.response.text == 'test'
}
}
Because the content of the _milestoneSummary.gsp is very long, I use the approach mentioned in both Grails documentation and http://www.javacodegeeks.com/2013/09/grails-goodness-unit-testing-render-templates-from-controller.html which is using views['/milestonesMgt/_milestoneSummary.gsp'] to mock the template. However, the response is still the original long content? Does anyone know what is wrong with my code? Thanks very much!!!
BTW when using params/response/model, I have to use controller.xxx, but I see the sample code in documentation use params/response/model directly, do you know why?
I am using Grails 2.3.8
the project link http://github.com/jackyying1130/MMS
the test is located in MMS/test/integration/phdmilestonemanagementsystem/MilestonesMgtControllerSpec.groovy
I have a service method that locks a database row.
public String getNextPath() {
PathSeed.withTransaction { txn ->
def seed = PathSeed.lock(1)
def seedValue = seed.seed
seed.seed++
seed.save()
}
}
This is how my spock test looks like:
void "getNextPath should return a String"() {
when:
def path = pathGeneratorService.getNextPath()
then:
path instanceof String
}
It's just a simple initial test. However I get this error when I run the test:
java.lang.UnsupportedOperationException: Datastore [org.grails.datastore.mapping.simple.SimpleMapSession] does not support locking.
at org.grails.datastore.mapping.core.AbstractSession.lock(AbstractSession.java:603)
at org.grails.datastore.gorm.GormStaticApi.lock_closure14(GormStaticApi.groovy:343)
at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:302)
at org.grails.datastore.gorm.AbstractDatastoreApi.execute(AbstractDatastoreApi.groovy:37)
at org.grails.datastore.gorm.GormStaticApi.lock(GormStaticApi.groovy:342)
at com.synacy.PathGeneratorService.getNextPath_closure1(PathGeneratorService.groovy:10)
at org.grails.datastore.gorm.GormStaticApi.withTransaction(GormStaticApi.groovy:712)
at com.synacy.PathGeneratorService$$EOapl2Cm.getNextPath(PathGeneratorService.groovy:9)
at com.synacy.PathGeneratorServiceSpec.getNextPath should return a String(PathGeneratorServiceSpec.groovy:17)
Does anyone have any idea what this is?
The simple GORM implementation for Unit tests does not support some features, such as locking. Moving your test to an integration test will use the full implementation of GORM instead of the simple implementation used by unit tests.
Typically when you find yourself using anything more than the very basic features of GORM you will need to use integration tests.
Updated 10/06/2014
In more recent versions of Grails and GORM there is now the HibernateTestMixin which allows you to test/use such features in Unit tests. Further information can be found in the documentation.
As a workaround, I was able to get it working by using Groovy metaprogramming. Applied to your example:
def setup() {
// Current spec does not test the locking feature,
// so for this test have lock call the get method
// instead.
PathSeed.metaClass.static.lock = PathSeed.&get
}
I have a problem while running fixtureLoader.load in BootStrap.groovy.
import grails.plugin.fixtures.FixtureLoader
class BootStrap {
def fixtureLoader
def init = { servletContext ->
environments {
test {
fixtureLoader.load {
build {
device1(Device, name: "device1")
device2(Device, name: "device2")
device3(Device, name: "device3")
}
}
}
}
}
def destroy = {
}
}
When Grails starts integration test phase, the load is executed. Then when Grails starts functional test phase, the load is executed another time without cleaning previous execution.
Thats means:
If I run with "test-app functional:" or "test-app integration:" everything is all right.
If I run with "test-app" both functional and integration tests are executed.
This is the JSON representation of data at functional test phase (running with "test-app"):
[[name:device3], [name:device2], [name:device1],[name:device3], [name:device2], [name:device1]]
This is same JSON representation of data at functional test phase (running with "test-app functional:")
[[name:device3], [name:device2], [name:device1]]
How to avoid this duplicates?
Thanks in advance
The default test database is a non-persistant in-memory hsqldb that gets discarded at the end of your tests, but changes to it will carry over between test phases. Also, integration testing rolls back changes after each test, but this doesn't apply to database changes made in Bootstrap.groovy.
One simple way to fix this is to simple check for the existence of the fixtures before trying to create them. For example:
environments {
test {
if (Device.count() == 0) {
// build fixtures
}
}
}
Another possible solution is to use separate databases for integration and functional tests. There's an example of how to do it at http://www.redtoad.ca/ataylor/2011/02/setting-grails-functional-test-database/