GEB: set default environment? - groovy

I declared a few environments in GebConfig via environments {} closure.
And if I specify -Dgeb.env in command line, everything works perfectly.
But when I start a single test for debugging purposes, I don't want to explicitly pass any additional environment variables.
What is the way to define the environment to be used by GEB as a default?

Just define a default driver outside of the environments My Geb config looks like this:
driver = {
new HtmlUnitDriver(true)
}
environments {
html_unit {
driver = {
new HtmlUnitDriver(true)
}
}
phantomjs {
driver = {
WebDriverManager.phantomjs().version("2.1.1").setup()
def pjsDriver = new PhantomJSDriver()
pjsDriver.manage().window().size = new Dimension(1024, 768)
pjsDriver
}
}
chrome {
driver = {
// (...)
}
}
chrome_headless {
System.setProperty("webdriver.chrome.logfile", "chromedriver.log")
System.setProperty("webdriver.chrome.verboseLogging", "true")
driver = {
// (...)
}
}
firefox {
driver = {
// (...)
}
}
ie {
driver = {
// (...)
}
}
edge {
driver = {
// (...)
}
}
opera {
driver = {
// (...)
}
}
win_app {
driver = {
// (...)
}
}
}

Related

Groovy ConfigSlurper is only partially building the structure when parsed

I am building a library for myself and using ConfigSlurper to parse a config.groovy file, and other config sources into an aggregated ConfigObject that I am using Micronaught compile time IOC to inject
#Bean
#Named('config')
ConfigObject config () {
Map envMap = [:]
def sysProps = System.getenv()
if (System.getProperty("env") ) {
envMap = System.getenv().findResult { it.key?.toLowerCase().contains "env" }.collect { [(it.key?.toLowerCase().substring(0, 2)): it.value.toLowerCase()] }
} else
envMap.get ('env', "development")
def env = envMap.get('env')
def resourcePath = "src${File.separatorChar}${env =="test" ?: "main"}${File.separatorChar}resources${File.separatorChar}"
ConfigObject config = new ConfigSlurper().parse(new File("${resourcePath}ApplicationConfig.groovy").text /*.toURI().toURL()*/)
config.put('systemProperties', sysProps)
config.putAll(envMap)
config.put('projectPath', System.getProperty("user.dir"))
config.put('resourcesPath', resourcePath.toString())
File resourceDirectory = new File ("${System.getProperty("user.dir")}$File.separatorChar$resourcePath")
FilenameFilter filter = {file, name -> name.matches(~/^.*properties$/) }
List propsFiles = resourceDirectory.listFiles (filter)
filter = {file, name -> name.matches(~/^.*yaml$/) }
List yamlFiles = resourceDirectory.listFiles (filter)
propsFiles.each {file ->
Properties prop = new Properties()
prop.load(new FileInputStream (file) )
Map propsMap = [:]
for (key in prop.stringPropertyNames()) {
propsMap.put(key, prop.getProperty(key))
}
config.putAll(propsMap)
}
yamlFiles.each {file ->
def yamlConfig = new YamlSlurper().parseText(file.text)
config.putAll(yamlConfig)
}
config
}
the resources/applicationConfig.groovy file looks like this
framework {
environments {
development {
server = "local" // choice of {local|clustered}
vertxOptions {
}
}
test {
server = "local" // choice of {local|clustered}
vertxOptions {
}
}
production {
server = "clustered" // choice of {local|clustered}
vertxOptions {
}
}
}
}
The code parses the groovy file but when I look at what in the configObject, its created the tope level framework map entry - but the lower levels are not there.
calling configObject.framework in code returns the object but it is of size() == 0!
I don't understand why the rest of the structure is not getting built.
Can any one advise why the internal structure is not being parsed and built.
Can anyone suggest what I have done wrong ?
I have just done a stripped back version like this
def configText = """
framework {
environments {
development {
server = "local" // choice of {local|clustered}
vertxOptions {
}
}
test {
server = "local" // choice of {local|clustered}
vertxOptions {
}
}
production {
server = "clustered" // choice of {local|clustered}
vertxOptions {
}
}
}
}
"""
ConfigObject conf = new ConfigSlurper().parse(configText)
assert conf.framework?.environments?.size() == 3
where the error shows this
Caught: Assertion failed:
assert conf.framework?.environments?.size() == 3
| | | | |
| | [:] 0 false
| ['environments':[:]]
['framework':['environments':[:]]]
Assertion failed:
assert conf.framework?.environments?.size() == 3
| | | | |
| | [:] 0 false
| ['environments':[:]]
['framework':['environments':[:]]]
at scripts.configSlurperTest.run(configSlurperTest.groovy:33)
at
The environments section when parsed by configslurper is conditional to the environment you pass to the constructor of ConfigSlurper itself.
Lets say you want the development config to be the default, but then you want to override this when run in test or production, you would do the following:
def configText = """
framework {
// defaults
mode = 'development'
server = "local" // choice of {local|clustered}
vertxOptions {
}
environments {
// test settings
test {
mode = 'testing'
server = "local" // choice of {local|clustered}
vertxOptions {
}
}
// production settings
production {
mode = 'live!'
server = "clustered" // choice of {local|clustered}
vertxOptions {
}
}
}
}
"""
// Default values
assert new ConfigSlurper().parse(configText).framework.mode == 'development'
// Test values
assert new ConfigSlurper('test').parse(configText).framework.mode == 'testing'
// Production values
assert new ConfigSlurper('production').parse(configText).framework.mode == 'live!'

Serenity Cucumber4 Environment URL on Page Objects not working

Why does this not work?
When I run the feature file as "Run as Cucumber Feature" I get an error
java.lang.AssertionError: Undefined default URL for page object PageObject
Page Object
#DefaultUrl("page:register.page")
public class AccountCreationPage extends PageObject {
...
}
Config File (serenity.config)
environments {
local {
webdriver.base.url = "https://localhost"
}
demo {
webdriver.base.url = "https://demo.example.com"
}
prod {
webdriver.base.url = "https://example.com"
}
all {
home.page = "#{webdriver.base.url}"
register.page = "#{webdriver.base.url}/register"
}
}
https://johnfergusonsmart.com/environment-specific-configuration-in-serenity-bdd/
shows the use of #DefaultUrl("page:register.page")
Serenity-Cucumber4. Java. Eclipse.
the config file is required to have default as an entry 🤦
environments {
default {
webdriver.base.url = "https://localhost"
}
...
all {
home.page = "#{webdriver.base.url}"
register.page = "#{webdriver.base.url}/register"
}
}

Passing different parameters to created jobs

On Jenkins, using Job DLS plugin, I'm trying to prepare one script which will create jobs configured for different environments (dev and preprod). Depends on for which environments this job has to run, different parameters are needed.
In this situation how to define, in the shortest way, that parameters for dev environment include the same as preprod parameters plus additionally i.e. 2 more?
An example of the code which I use is presented below.
def environments = ["DEV", "PREPROD"]
def names = ["name1", "name2", "name3"]
def jobParameters = {
string {
name("browser")
defaultValue("CHROME")
description("Browser on which one tests will run")
trim(true)
}
string {
name("parameter1")
defaultValue("")
description("")
trim(true)
}
}
def jobParametersDev = {
jobParameters
string {
name("parameter2")
defaultValue("")
description("")
trim(true)
}
string {
name("parameter3")
defaultValue("")
description("")
trim(true)
}
}
def createJob(name, env, runCommand, jobParameters) {
job("Job-${-> name}-${-> env}") {
description("My first job for ${-> name}")
parameters(jobParameters)
steps {
shell {
command(runCommand)
}
}
}
}
for (name in names) {
for (env in environments) {
if (env == 'DEV') {
def runCommand = "python35 -u ./TestSuite-${-> name}.py %parameter1% %parameter2%,%parameter3% %browser%"
createJob(name, env, runCommand, jobParametersDev)
} else {
def runCommand = "python35 -u ./TestSuite-${-> name}.py %parameter1% ${-> env} %browser%"
createJob(name, env, runCommand, jobParameters)
}
}
}
To summarise - the last thing which I tried is:
def jobParametersDev = {
jobParameters
...
}
But it doesn't work... Only values for jobParametersDev are visible.
How to add these values? If it's not necessary I don't want to double the same code.
I will be really grateful for any help.
You can not simply call one closure within another. But you can chain method calls. You just need to pass the job reference.
def generateParameters = { job ->
job.parameters {
stringParam('param3', '', '')
// more params here...
}
}
def generateDevParameters = { job ->
generateParameters(job)
job.parameters {
stringParam('param4', '', '')
// more params here...
}
}
def createJob(name, generateParameters) {
def j = job(name) {
// more config here...
}
generateParameters(j)
}
createJob('test1', generateParameters)
createJob('test2', generateDevParameters)

aio_write failing on release builds

I'm using aio_write it is working in a debug build but not in release. I've checked the constructor that everything is initialized and I'm not getting any warnings about uninitialized variables. The class collects data that is to be written to disc in 16K chunks. If the data is less than 16K, it works, even in release builds. If the data is larger than 16K, only the first chunk is written. WriteBuffer::ContinueWriteToFile returns WriteFileState_Active indefinitely.
WriteBuffer_posix.h:
class WriteBufferPlatformData
{
public:
WriteBufferPlatformData();
~WriteBufferPlatformData();
aiocb aioData;
WriteBuffer::BufferVector::iterator currentBuffer;
};
WriteBuffer_posix.cpp:
WriteBufferPlatformData::WriteBufferPlatformData() :
aioData(),
currentBuffer()
{
memset(&aioData,0,sizeof(aioData));
aioData.aio_fildes=-1;
}
WriteBufferPlatformData::~WriteBufferPlatformData()
{
if (0<=aioData.aio_fildes) {
close(aioData.aio_fildes);
}
}
WriteBuffer::WriteFileState WriteBuffer::StartWriteToFile(const char * filename)
{
NYMPH_ASSERT(0>m_platformData->aioData.aio_fildes);
m_platformData->aioData.aio_fildes=open(filename,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
NYMPH_ASSERT2(0<=m_platformData->aioData.aio_fildes,"Could not open file for writing: %s (%d)",filename,errno);
if (0>m_platformData->aioData.aio_fildes) {
return WriteFileState_Failed;
}
if (m_buffers.empty()) {
close(m_platformData->aioData.aio_fildes);
m_platformData->aioData.aio_fildes=-1;
return WriteFileState_Complete;
}
m_isWriting=true;
m_platformData->currentBuffer=m_buffers.begin();
return ContinueWriteToFile();
}
WriteBuffer::WriteFileState WriteBuffer::ContinueWriteToFile()
{
NYMPH_ASSERT(0<=m_platformData->aioData.aio_fildes);
if (0!=m_platformData->aioData.aio_nbytes) {
int writeErrno=aio_error(&(m_platformData->aioData));
if (EINPROGRESS==writeErrno) {
return WriteFileState_Active;
}
NYMPH_ASSERT(aio_return(&(m_platformData->aioData))==m_platformData->aioData.aio_nbytes);
m_platformData->aioData.aio_nbytes=0;
++(m_platformData->currentBuffer);
if (m_buffers.end()==m_platformData->currentBuffer) {
close(m_platformData->aioData.aio_fildes);
m_platformData->aioData.aio_fildes=-1;
return WriteFileState_Complete;
}
}
if (0==m_platformData->aioData.aio_nbytes) {
m_platformData->aioData.aio_buf=*(m_platformData->currentBuffer);
if (m_buffers.back()==m_platformData->aioData.aio_buf) {
m_platformData->aioData.aio_nbytes=m_offset;
} else {
m_platformData->aioData.aio_nbytes=kBufferSize;
}
m_platformData->aioData.aio_offset=lseek(m_platformData->aioData.aio_fildes,0,SEEK_END);
if (0!=aio_write(&(m_platformData->aioData))) {
m_platformData->aioData.aio_nbytes=0;
NYMPH_ASSERT(EAGAIN==errno);
if (EAGAIN!=errno) {
close(m_platformData->aioData.aio_fildes);
m_platformData->aioData.aio_fildes=-1;
return WriteFileState_Failed;
}
}
}
return WriteFileState_Active;
}
Despite what I have read in the man page, it seems that calling aio_return is required and changing the NYMPH_ASSERT(aio_return... to NYMPH_VERIFY(aio_return... corrected the problem.

Custom init on test/development mode in Grails

I want to run specific login in BootStrap class depending on development or test mode is currently used.
How can I do this?
From the documentation:
class Bootstrap {
def init = { ServletContext ctx ->
environments {
production {
// prod initialization
}
test {
// test initialization
}
development {
// dev initialization
}
}
}
...
}
import grails.util.Environment
class BootStrap {
def init = { servletContext ->
def currentEnv = Environment.current
if (currentEnv == Environment.DEVELOPMENT) {
// do custom init for dev here
} else if (currentEnv == Environment.TEST) {
// do custom init for test here
} else if (currentEnv == Environment.PRODUCTION) {
// do custom init for prod here
}
}
def destroy = {
}
}
from the official docs
Programmatic Environment Detection
Within your code, such as in a Gant script or a bootstrap class you can detect the environment using the GrailsUtil class:
import grails.util.GrailsUtil
...
switch(GrailsUtil.environment) {
case "development":
configureForDevelopment()
break
case "production":
configureForProduction()
break

Resources