Serenity BDD - Can I define step in such way that Cucumber datatable columns contains only allowed values? - datatable

I have following step:
And I verify results for 'param1AllowedValue1' with 'param2AllowedValue3'
that is defined in following way:
#And("{word} verify results for {param1} with {param2}")
public void someMethod(String nameOfActor, Param1 param1, Param2 param2) {}
#ParameterType("'(param1AllowedValue1|param1AllowedValue2|param1AllowedValue3)'")
public Param1 param1(String param1) {return ...}
#ParameterType("'(param2AllowedValue1|param2AllowedValue2|param2AllowedValue3)'")
public Param2 param1(String param2) {return ...}
which immediatelly makes it easy to see if I have Not used correct value for param1 or param2: IDE shows step as not recognized one.
Now I want to redefine the step, so that instead of repeating steps:
And I verify results for 'param1AllowedValue1' with 'param2AllowedValue3'
And I verify results for 'param1AllowedValue2' with 'param2AllowedValue2'
And I verify results for 'param1AllowedValue3' with 'param2AllowedValue1'
I could use only one step with datatable:
And I verify results for:
| param1 | param2 |
| param1AllowedValue1 | param2AllowedValue3 |
| param1AllowedValue2 | param2AllowedValue2 |
| param1AllowedValue3 | param2AllowedValue1 |
My question is how can I make it possible that param1 and param2 values will be verified against the allowed values - the same as in case of parameter type.
I've found only an example when values are just read from the Datatable, not verified: https://cucumber.io/docs/cucumber/configuration/

You can do this in Cucumber by mapping your table to a List<Parameters> where:
record Parameters(P1 p1, P2 p2)
enum P1 { Value1, Value2 }
enum P2 { Value1, Value2 }
Then your mapping tool can tell you that the value was not valid.
For example using
public class DataTableStepDefinitions {
private final ObjectMapper objectMapper = new ObjectMapper();
#DefaultParameterTransformer
#DefaultDataTableEntryTransformer
#DefaultDataTableCellTransformer
public Object defaultTransformer(Object fromValue, Type toValueType) {
return objectMapper.convertValue(fromValue, objectMapper.constructType(toValueType));
}
}
Docs:
https://github.com/cucumber/cucumber-jvm/tree/main/java#data-table-type
https://github.com/cucumber/cucumber-jvm/tree/main/datatable
Notes:
Unfortunately there is no IDE integration for data tables.
This works for Cucumber, I don't know if it will work with Serenity.

Related

Getting issue while comparing one property to another in JMeter

In my JMeter test plan, I want to set a flag in case of failure in every HTTP request. So I created a JSR223 PostProcessor in request with the following snippet:
if (!prev.isSuccessful()) {
int abc = 1
props.put('result', vars.get('abc'))
}
where result is defined as global in the thread.
In teardown I want to exit JMeter by comparing with the value of the flag . So I am doing the following:
if ((props.get('result') as int) == 1) {
System.exit(1);
}
Can anyone help me what wrong I am doing in this? Is there any other way by which I can do this.
This statement vars.get('abc') will return null because you just declare an integer called abc and not writing it to JMeter Variables.
You need to amend your code to something like:
if (!prev.isSuccessful()) {
int abc = 1
props.put('result', abc)
}
also there is no need to cast it to the integer back, it's stored as the object of the given type
if (props.get('result') == 1) {
System.exit(1);
}
More information:
Properties aka props
JMeterVariables aka vars
Top 8 JMeter Java Classes You Should Be Using with Groovy
You may also find AutoStop Listener useful

How to use parameter values from file instead parameters define in jenkin pipeline

I want to use a parameters values define in file instead the one define in parameters declarative. instead of YourName and environment define in pipeline script if i want to use the one define in parameters.txt file stored in /tmp/ directory. how we can use in jenkin pipeline script?
the reason to use this when running a nightly job we can define values to be use, since the extendedChoice parameters in declarative has a multiple values.
parameters {
string name: 'YourName', defaultValue: 'PQR', description: 'User Name'
}
environment {
MyENV="anyURL"
}
It's not immediately clear from your question what exactly are you trying to achieve, but there are two relevant options.
One is to use parameterizedCron plugin and to supply the parameters, if you know them at the time of your job definition, e.g. like this:
pipeline {
triggers {
parameterizedCron("H 1-5 * * * % MY_NAME=maratc; YOUR_NAME=veer1987")
}
}
Assuming there are string parameters named MY_NAME and YOUR_NAME, they will receive the values provided.
The other one is for when you don't know the values at the job definition time and really only know them at the time of running the job. Assuming the values are written in /${WORKSPACE}/nightly_params.txt on the machine having master label:
YOUR_NAME = null
echo "This should be null: YOUR_NAME is ${YOUR_NAME}"
node('master') {
stage("Define variable") {
YOUR_NAME = readFile("${WORKSPACE}/nightly_params.txt").trim()
echo "This is after reading the file: YOUR_NAME is ${YOUR_NAME}"
}
}
pipeline {
agent any
stages {
stage("Use variable") {
steps {
echo "The YOUR_NAME variable is: ${YOUR_NAME}"
}
}
}
}

Extracting part of a string on jenkins pipeline

I am having some trouble with the syntax in my pipeline script.
I am trying to capture everything after the last forward slash "/" and before the last period "." in this string git#github.com:project/access-server-pd.git (access-server-pd)
Here (below) is how I would like to set it up
MYVAR="git#github.com:project/access-server-pd.git"
NAME=${MYVAR%.*} # retain the part before the colon
NAME=${NAME##*/} # retain the part after the last slash
echo $NAME
I have it current set up with triple quotes on the pipeline script:
stage('Git Clone') {
MYVAR="$GIT_REPO"
echo "$MYVAR"
NAME="""${MYVAR%.*}"""
echo "$NAME"
But I am receiving an unexpected token on "." error. How might I write this so that I can get this to work?
UPDATE: This command does the trick:
echo "git#github.com:project/access-server-pd.git" | sed 's#.*/\([^.]*\).*#\1#'
Now I just need to find the proper syntax to create a variable to store that value.
In this case, it looks like using a few Groovy/Java methods on the String can extract the parts.
final beforeColon = url.substring(0, url.indexOf(':')) // git#github.com
final afterLastSlash = url.substring(url.lastIndexOf('/') + 1, url.length()) // project/access-server-pd.git
This uses a few different methods:
public int String.indexOf(String str, int fromIndex)
public String String.substring(int beginIndex, int endIndex)
public int String.length()
public int String.lastIndexOf(String str)
You do need to be careful about the code you use in your pipeline. If it is sandboxed it will run in a protected domain where every invocation is security checked. For example, the whitelist in the Script Security Plugin whitelists all of the calls used above (for example, method java.lang.String lastIndexOf java.lang.String).
Performing String manipulation in your pipeline code is perfectly reasonable as you might make decisions and change your orchestration based on it.

How can we set the value to the header dynamically in SOAPUi?

I'm new to SoapUI. I wanted to know how can we add 2 property value into one Header value.
For instance, I got some response like in XML format:
<Response xmlns="Http://SomeUrl">
<access_token>abc</access_token>
<scope>scope1</scope>
<token_type>Bearer</token_type>
</Response>
I want to send both access_token & token type to a single header value like:
"Authorization":"Bearer abc"
I am not getting how to do this using property transfer step.
Can anyone please help me?
You can use XPath concat function to concatenate the both values in one variable in your property transfer steps, in your case you can use the follow XPath:
concat(//*:token_type," ",//*:access_token)
concat function concatenates two or more strings, //*:token_type gets the Bearer value and //*:access_token gets the abc.
Hope this helps,
Add a script step after the step returning what you describe above.
def tokenType = context.expand('${STEP RETURNING STUFF#Response#//Response/token_type}');
def token = context.expand('${STEP RETURNING STUFF#Response#//Response/access_token}');
//add header to all steps
for (def stepEntry : testRunner.testCase.testSteps) {
if (!(stepEntry.value instanceof com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep)) {
continue;
}
def headers = stepEntry.value.httpRequest.requestHeaders;
headers.remove("Authorization");
headers.put("Authorization", token_type + " " + token);
stepEntry.value.httpRequest.requestHeaders = headers;
}
Here is another way without using additional property transfer step, but uses script assertion
Add a script assertion for the request test step.
Use below code into that script, modify element XPath are required
def element1Xpath = '//*:token_type'
def element2Xpath = '//*:access_token'
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def response = groovyUtils.getXmlHolder(messageExchange.responseContentAsXml)
def field1 = response.getNodeValue(element1Xpath)
def field2 = response.getNodeValue(element2Xpath)
if (!field1) { throw new Error ("${element1Xpath} is either empty or null") }
if (!field1) { throw new Error ("${element2Xpath} is either empty or null") }
context.testCase.setPropertyValue('TEMP_PROPERTY', "${field1} ${field2}")
Now the expected value(merged) is available in a property 'TEMP_PROPERTY'. You may rename the property name as you wish in the last line of the code.
You may the new wherever it is needed within the test case.

What is use of '%s' in xpath

I have tried to know the reason in online but i didnt get it.
I want to know the reason why '%s' used in xpath instead of giving text message
I hope some one can help me on this.
see my scenario:
By.xpath(("//div[contains(text(),'%s')]/following-sibling::div//input"))
It's called wildcard.
E.g. you have
private final String myId = "//*[contains(#id,'%s')]";
private WebElement idSelect(String text) {
return driver.findElement(By.xpath(String.format(myId, text)));
}
Then, you can make a function like:
public void clickMyId(idName){
idSelect(idName.click();
}
And call
clickMyId('testId');
The overall goal of the %s is not using the string concatenation, but to use it injected into a string.
Sometimes, there are many locators for web elements which are of same kind, only they vary with a small difference say in index or String.
For e.g., //div[#id='one']/span[text()='Mahesh'] and
//div[#id='one']/span[text()='Jonny']
As it can been seen in the above example that the id is same for both the element but the text vary.
In that case, you can use %s instead of text. Like,
String locator = "//div[#id='one']//span[text()='%s']";
private By pageLocator(String name)
{
return By.xpath(String.format(locator, name));
}
So in your case,
By.xpath(("//div[contains(text(),'%s')]/following-sibling::div//input"))
the text is passed at runtime as only the text vary in the locator.
'%s' in XPath is used as String Replacement.
Example:
exampleXpath = "//*[contains(#id,'%s')]"
void findElement(String someText)
{
driver.findElement(By.xpath(String.format(exampleXpath, someText)));
}
So it will replace %s with someText passed by user.

Resources