I am getting weird error in my geb functional tests.
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Spec expression: 1: expecting '}', found 'assert' # line 1, column 71.
} ) { at(JobOfferDetailPage) assert des
My test looks like this. I click on a link which opens a new window with details of the job offer. Than I want to assert some text on the new page using Page Pattern.
Test:
withNewWindow( { quickShowOption.click() } ) { //TODO fix me
at(JobOfferDetailPage)
assert description.text() == 'some text'
assert requirements.text() == 'some text'
assert advatages.text() == 'some text.'
assert categories.text() == 'some text'
assert locality.text() == 'some text'
}
Page:
class JobOfferDetailPage extends Page {
static at = {$('#contactLabel').text() == 'Contact'}
static content = {
description {$('#jobOfferDescription')}
requirements {$('#jobOfferRequirements')}
advatages {$('#jobOfferAdvantages')}
jobOfferType {$('#jobOfferType')}
categories {$('#categories')}
locality {$('#locality')}
startDate {$('#startDate')}
requiredLanguages {$('#requiredLanguages')}
}
}
I get compilation error after my conditions are asserted. If I make a typo in asserted text than the test will fail normally, but if it passes, than it fails with this weird error.
Thank you #Erdi.
I use spock,geb versions "0.13.1" and selenium version "2.51.0".
If one was to believe this comment in one of Geb's own tests, which was nota bene written by me some time ago, this indeed seems like some sort of bug in Spock. What is interesting is that I just now moved that statement to an expect block and it works as long as the last statement in the second closure passed to newWindow() evaluates to true. This makes me think that it is an issue with old version of Spock and/or Groovy. Which versions of the aforementioned tools are you using?
One possible workaround would be to move your statement from expect/then to one that is not asserting (given or when) as shown in the test I linked to.
Related
this is very tough to me to understand how Jenkins works. In general when you read documentation and define pipeline, things go smooth. I understand pipelines, stages, steps, scripts. What I don't understand is declaration vs runtime. Especially when it comes to WHEN declaration and evaluating expression. For example:
What is the form of expression? Should it return something like: return true; or maybe it should be statement like: true
When it gets executed? If I access params.MY_PARAMETER_FROM_INPUT, do WHEN has access to its value picked by user?
Is it possible to switch execution between runtime vs pipeline declaration time?
Can I ask for stage (input with message box) only if given condition within WHEN is meet and if not, then don't ask for it but run stage anyway?
When you use IF from script and when WHEN from stage. Can WHEN be defined else where? Within steps, scripts, pipeline?
For example in a stage I've put when { expression { params.ENV == 'prod' } } input { message "Really?" ok "Yeah!" } but the expression was ignored and the question was always asked (current understanding is that it should skip stage/abort whole pipeline when ENV input param is different than "prod" value)
Any thoughts?
OK. Using existing semantic of Jenkins I have manage to achieve what I wanted with following snippet:
stage('Confirm if production related') {
when {
beforeInput true
expression { params.ENV == 'production'; }
}
input {
message "Should I deploy to PRODUCTION?"
ok "Yes, do it!"
}
steps {
script { _ }
}
}
Not bad but not good either.
I have the following Spock test, which passes:
def "test"() {
given:
def name = "John"
expect:
name.length() == 4
when:
name = name.concat(name)
then:
name.length() == 8
}
But when I modify the last then block and make it an expect block...
// previous part same
expect:
name.length() == 8
I am getting:
Groovy-Eclipse: Groovy:'expect' is not allowed here; instead, use one of: [and, then]
Is it because multiple expect blocks are not allowed in a single test? If so, is this documented anywhere? There is a similar test here written with given - expect - when - then but it is not clear why a second expect was not used, although what is being asserted is same, just being flipped.
when-expect is simply a syntax error with regard to Spock's specification DSL. The compiler message already tells you how to solve your problem. After when you need then (or and first, if you want to structure your when block into multiple sections). In contrast, expect is a kind of when-then contracted into a single block, because both the stimulus and verifying the response in a condition appear together. Block labels and how to use them is documented here.
Under Specifications as Documentation, you learn more about why you might want to use and and block labels. Under Invocation Order you learn about what you can achieve by using multiple then blocks in contrast to then-and.
You can use multiple expect blocks within one feature, no problem. But you do need to make sure that your when-then (if any) is complete, before you can use another expect.
For example, this is a valid feature:
def "my feature"() {
given: true
and: true
and: true
expect: true
when: true
and: true
then: true
and: true
then: true
expect: true
and: true
cleanup: true
}
I'm fairly new to Groovy and Jenkins, so hopefully this question is coherent.
I have a Jenkinsfile written in Groovy and would like to validate one of the params as a valid URI. Without writing my own regex check, is there a library I could easily invoke during Jenkins startup?
You can try this:
try {
def foo = new java.net.URL("yourURI").openStream()
if (foo.getClass() == sun.net.www.protocol.http.HttpURLConnection$HttpInputStream) {
println 'valid'
foo.close()
}
}
catch (java.io.FileNotFoundException e) {
println 'not valid'
return
}
Unfortunately URL.toUri is not allowed at least in our setup. (It could possibly be allowed with a separate config.) Apparently opening the url (trying to connect to the host) could be possible, but that feels like it could cause other problems.
I ended up with this:
// Validation URLs in Jenkins script is hard (URL.toUri is banned). This regex roughly matches the subset of
// URLs we might want to use (and some invalid but harmless URLs). You can get a rough sense what
// this matches with a generation tool like https://www.browserling.com/tools/text-from-regex .
def saneUrlPattern = ~/^https:\/\/[-\w]{1,32}(\.[-\w]{1,32}){0,4}(:[0-9]{1,5})?(\/|(\/[-\w]{1,32}){1,10})?(\?([-\w]{1,32}=[-\w]{0,40}(&[-\w]{1,32}=[-\w]{0,40}){1,8})?)?(#[-\w]{0,40})?$/
if (!(params.sourceUrl =~ saneUrlPattern)) {
return [error: "Invalid url ${params.sourceUrl}. A simple https URL is expected."]
}
I realise that trying to validate URLs with a regular expression is difficult. I tried to strike a balance between strict and correct enough validation and a regular expression that has some hope of being understood by looking at it and being reasonably convinced as to what it actually matches.
I'm a pretty raw Grails newb but I know some Groovy and I have a Java background. This is an ancient test app I'm updating to Java 8 from Java 6.
Context: Grails 2.3.9 / Java 1.8.0_101
The test that is failing is:
#TestFor(PillsController)
#Mock(Pills)
class PillsControllerTests {
...
void testUpdate() {
controller.update()
assert flash.message != null
assert response.redirectedUrl == '/somethingPills/list'
response.reset()
populateValidParams(params)
def somethingPills = new SomethingPills(params)
assert somethingPills.save() != null
params.id = somethingPills.id
controller.update()
assert view == "/somethingPills/edit" //<--- FAILS HERE. VIEW IS NULL.
assert model.somethingPillsInstance != null
somethingPills.clearErrors()
populateValidParams(params)
controller.update()
assert response.redirectedUrl == "/somethingPills/show/$somethingPills.id"
assert flash.message != null
response.reset()
somethingPills.clearErrors()
populateValidParams(params)
params.id = somethingPills.id
params.version = -1
controller.update()
assert view == "/somethingPills/edit"
assert model.somethingPillsInstance != null
assert model.somethingPillsInstance.errors.getFieldError('version')
assert flash.message != null
}
}
I assume "view" is a reference to some codified variant of Model/View/Controller.
I found the update at the top confusing. Update what if nothing has been saved? I tried moving populate and SomethingPills declaration above update. The result was that view was still null. How can I predict what view will be?
Another thing I noticed. If I click on the update method, I see that there are two parameters. I'm assuming that Groovy allows you pass no parameters by default or I would be seeing an error about that. I don't know if this is how it is supposed to work but if I pull the ID & version from SomethingPills and pass them then I get /somethingPills/show/1" instead of null but still not "/somethingPills/edit".
[EDIT] I've found this: http://docs.grails.org/2.3.9/guide/scaffolding.html
Go to your PillsController.groovy file and find the update() method.
See if you have a statement like
render view:'/somethingPills/edit', ....
In the unit test, view refers to the path of the gsp file that the controller renders.
I am pretty sure there would be some logic in the update() method, which you need to post if the unit test still fails. Form the unit test, it looks like as if some condition matches, then it renders the gsp template otherwise it redirects.
I have two class:
class Foo {
String doSomething(String a, String b) {
return 'Not Working'
}
}
class Bar {
String methodIWannaTest() {
return new Foo().doSomething('val1', 'val2')
}
}
And I want to replace 'doSomething' in a test but it dosent work
class BarTests {
#Test
void testMethodIWannaTest() {
Foo.metaClass.doSomething {String a, String b -> return 'Working'}
assert new Bar().methodIWannaTest() == 'Working' //THIS TEST FAIL, return 'Not Working'
}
}
*I know the test doesn't really make sens, it's just to show my point
What do I do wrong ? Is it possible to do it without using 'mockFor' ?
I would suggest you to start the test afresh. Baby Steps is what I follow. :)
Create a new grails app.
Create both Foo and Bar inside src/groovy under a package.
Create unit test case from command prompt. Put the desired test code.
Execute grails test-app
[Grails v2.2.0]
Another alternative is to use Groovy MockFor.
def mock = MockFor(Foo)
mock.demand.doSomething = {String a, String b -> return 'Working'}
mock.use {
assert new Bar().methodIWannaTest() == 'Working'
}
A downside is that there was a bug, making unit tests not clear the mock. This is fixed for 2.2.3.
I found the problem:
First, in my exemple, I forgot the '=' when defining the closure
Foo.metaClass.doSomething {String a, String b -> return 'Working'}
should be
Foo.metaClass.doSomething = {String a, String b -> return 'Working'}
While searching I also found that you cannot replace a method with optionnal parameters by a closure. Probably a bug
I tried this on GGTS 3.2.0 and got the following results.
Copied all the code and ran on Grails 2.2.2: everything worked correctly. However, then I commented out Foo.metaClass.doSomething = {String a, String b -> return 'Working'} line and, surprisingly, the test was still passing successfully. I did more changes and the metaClass just seemed to get "cached" between tests: changes had no effect.
Then I thought if it is possible that Grails were running in interactive mode. Went to Preferences > Groovy > Grails > Grails Launch and found a checkbox 'Keep external Grails running' ticked. Its tooltip even has the following words: 'Warning: experimental feature!'. Unticking that checkbox did the trick and the metaClass no longer got cached between test runs. I am still wondering why an exprimental feature would be turned on by default...