Serenity/js Cucumber Protractor : Tabs Capabilities & Features not visible in HTML reporting - serenity-js

I followed serenity-js guidelines but I don't see Capabilities and Feature tabs in HTML report. Only tests and acceptance criteria are visibles.
json output (maybe an issue with the path ???) :
{
"id":"test-num-1;test-dosomething",
"title":"Test something",
"name":"Test something",
"context":"chrome",
"description":"",
"startTime":1500459935525,
"duration":5360,
"testSource":"cucumber",
"manual":false,
"result":"SUCCESS",
"userStory":{
"id":"test-num-1",
"path":"test\\e2e\\features\\capability_1\\myFeature1.feature",
"storyName":"Test number 1",
"type":"feature"
},
"tags":[
{"name":"chrome","type":"browser"},
{"name":"Test num 1","type":"feature"}
],
"issues":[],
"testSteps":[
(...)
],
"annotatedResult":"SUCCESS"
}
Is there any issue with path "test\e2e\" that prefix "features" path ?
Thanks

The process of producing the Serenity BDD HTML reports consists of two phases:
As your test scenarios are executed, Serenity/JS generates .json and .png files under the outputDirectory
After your tests finish, Serenity/JS CLI (a node.js wrapper around the Serenity BDD CLI jar) processes the above files, as well as the Cucumber feature files, to produce the HTML reports
This means that in order to make both Serenity/JS and Serenity/JS CLI use a non-default directory you'd need to:
configure the outputDirectory of Serenity/JS
specify the source (location of .json reports and screenshots) and destination (target location for the HTML report) parameters to be the same as the outputDirectory for Serenity/JS, and also the features property (location of Cucumber feature files) when invoking Serenity/JS CLI
Hope this helps!
Jan

Related

How to add file to the 'Evidance' using Cucumber JSON Multipart into the jenkinsci/xray-connector-plugin

I'd like to add file to the Evidence for new test execution.
How to upload file to the Evidance input using Cucumber JSON Multipart?
Xray plugin repo: jenkinsci/xray-connector-plugin
There is my multipart JSON:
{
"fields": {
"project": {
"key": "${projectKey}"
},
"summary": "Test Execution for Cucumber results (Generated by job: ${BUILD_TAG})",
"description": "Test Execution for Cucumber results (Generated by job: ${BUILD_TAG})",
"issuetype": {
"id": "12453"
}
},
"xrayFields": {
"testPlanKey": "${testPlanKey}",
"environments": [
"${env}"
]
}
}
What should I add to this json to upload a file into Evidence input?
That Cucumber JSON multipart endpoint (similarly with other endpoints) doesn't provide a way to specify that field explicitly.
The Xray JSON format (and either the standard or multipart endpoints) will allow you to specify that information; however, this format is not the most adequate one in case you want to upload Cucumber related results.
You have two options, since in this case I guess we can exclude using Xray JSON format:
a) use Cucumber JSON (either standard or multipart endpoint) and take advantage of the fact that Xray can process attachments (i.e. screenshots) that you can embed in the cucumber steps implementation (please see example on Xray docs where it briefly mentions it). You should look at cucumber's API to see how that can be done in terms of API.
As we speak, in Java, I think you have to do +something like this in a hook
scenario.attach(data, "image/png", "My screenshot");
Example here.
b) you can use your current approach and then use the GraphQL to update the evidence on the corresponding Test Run. This will be tricky to implement as you'll need to know the Test Execution issue key, then it's id and then use the proper GraphQL request to update evidence on a specific Test Run inside that Test Execution... this is not trivial though.

cypress: execute setup method once before starting a feature

Have a requirement where before running the feature "abfeatureTest1" few initial data setup required for validation needs to be created through UI and is available in method "beforeFeatureTest1".
I need to execute the method "beforeFeatureTest1" only once before running the feature "abfeatureTest1" and discard the data after feature execution.
I am aware of After/Before all hooks and After/Before scenario hooks, But i need something like After/Before feature hook.
Any suggestions on how this can be achieved?
Thanks.
For Cypress-Cucumber, following hooks will run before and after each feature file but not after each scenario
before(()=>{
cy.log('======before=====')
})
after(()=>{
cy.log('======after=====')
cy.wait(5000)
})
You can have tags at FeatureFile level and at Scenario level.
So #FeatureFile3 tag will run all the cases in your FeatureFile3
and #FF1scenario2 tag will run only particular scenario
You can specify these tags in your runner class for execution as per your requirement.
#CucumberOptions(features= "src/main/resources/publish", tags="#FeatureFile3", format = {"pretty"} )

xml-flow NPM package - Unexpected XML Parsing Behaviour

Background
I am using xml-flow npm package to parse XML using streams. Issue is that the xml nodes are getting parsed in an unexpected way.
My intention is to parse a huge XML file using a repeating xml node. The XML file can be any URL and the repeating node will be provided from UI.
I tried to use the options with all possible values but the parsing behaviour doesn't seem to change.
Sample Code
I used following sample XML -
<list>
<item>
<details>
<id>1</id>
</details>
</item>
<item>
<details>
<id>2</id>
<description>description for item 2</description>
</details>
</item>
</list>
I tried to parse it using item as repeating node as follows -
const fs = require("fs");
const flow = require("xml-flow");
const xmlStream = flow(fs.createReadStream("./sample.xml"));
xmlStream.on('tag:item', function (person) {
console.log(JSON.stringify(person, null, 4));
});
I got following response for 2 parsed xml nodes -
// node 1
{
"$name": "item",
"details": "1"
}
// node 2
{
"$name": "item",
"details": {
"id": "2",
"description": "description for item 2"
}
}
Problem
As you can see in the response, I get a different JSON structure for parsed XML nodes.
In case of first XML node, <id> node didn't appear in JSON object (unlike second XML node) because its parent node viz. <details> has only one child node viz. <id>.
This is causing problems in my application as the parsed XML might have thousands of records & the relative path in JSON structure to the leaf nodes are changing because of this behaviour.
As an example, if there are 10000 records in xml file and all the records after 5000th record have node 2 structure, item.details relative path will point to a string for records 1 to 5000 whereas the same path will point to an object for remaining records.
Alternative NPM Package
I did try to use xml-stream which works on the same logic, but it comes with a problem of collecting the sub-items explained here which is even more complicated problem for me as incoming XML structure in this case will vary from file to file.
Let me know if I need to provide more information.
Cheers!
Well! After going through the implementation of these packages, it seems there is no workaround for this problem (I might have missed something) unless explicit support is provided.
I finally decided to write a new logic & ended up writing a new npm package xtreamer which provides xml nodes instead of converting them into JSON objects.
This package exposes a transform stream that can be piped with any readable stream. It expects xml node name in request and emits a custom event xmldata to output the xml node.
The output can the be plugged in to any xml-json npm package as per the requirement to get the final JSON. Check the npm package for further details.
supporting module
I managed to create one more npm package xtagger which uses sax npm package and provides xml structure in following format -
structure: { [name: string]: { [hierarchy: number]: number } };
This package can be used to find the repeating nodes in xml file by considering their hierarchy.

Passing list of values to Cucumber scenario outline

I have a scenario to validate 100 employee names, The QueryString will return them in xml format.All I want to do is to validate all the employee names in an Assertion statement like given below. Instead of adding each name in the Scenario Outline Example, Is it possible to send a list of 100 employee names as input so that I can Iterate through them in java and could easily validate in Assertion condition. Please advice.
Scenario Outline: When the User queries for employee information, the correct records are returned
Given the webservice is running
When the User queries for employee information "<QueryString>"
Then the User receives correct data "<Name>"
Examples:
|QueryString|Name|
|Some localhost url|Peter|
|Some localhost url|Sam|
.
.
#Then("^the User receives correct data\"([^\"]*)\"$")
public void the_user_receives_correct_data(String arg1) throws Throwable {
queryResultPage = selenium.getPageSource();
assertTrue(queryResultPage.contains(arg1));
}
so i will answere here to LINGS comment
What you can do, is use these filenames in your step definition to load the files in your code. Cucumber doesnt support direct file loading as far as i know.
i use something like this to locate full ressource pathes for my relative path file names:
public static String getAbsoluteResourcePath(String resourcePath) {
if (SystemUtils.IS_OS_WINDOWS) {
return Utils.class.getResource(resourcePath).getPath().substring(1).replace("/", File.separator);
} else {
return Utils.class.getResource(resourcePath).getPath().replace("/", File.separator);
}
}
The resourcePath should then be your relative file path
What you are looking for is external test data support, which is supported with QAF. You can use any inbuilt data provider with interceptor to modify data set or custom data provider.
If you are using cucumber version 5+ you can use qaf-cucumber that will give you all qaf features with cucumber. For lower version you can run your existing feature files with QAF runner.

How to use common/shared "blocks" between cucumber features?

I'm new to cucumber, but enjoying it.
I'm currently writing some Frank tests, and would like to reuse blocks of cucumber script across multiple features - I'd like to do this a the cucumber level if possible (not inside the ruby).
For example, I might have 4 scripts that all start by doing the same login steps:
given my app has started
then enter "guest" in "user-field"
and enter "1234" in "password-field"
and press "login"
then I will see "welcome"
then *** here's the work specific to each script ***
Is there any way to share these first 5 lines across multiple scripts? Some kind of "include" syntax?
Generally there are 2 approaches:
Backgrounds
If you want a set of steps to run before each of the scenarios in a feature file:
Background:
given my app has started
then enter "guest" in "user-field"
and enter "1234" in "password-field"
and press "login"
then I will see "welcome"
Scenario: Some scenario
then *** here's the work specific to this scenario ***
Scenario: Some other scenario
then *** here's the work specific to this scenario ***
Calling steps from step definitions
If you need the 'block' of steps to be used in different feature files, or a Background section is not suitable because some scenarios don't need it, then create a high-level step definition which calls the other ones:
Given /^I have logged in$/ do
steps %Q {
given my app has started
then enter "guest" in "user-field"
and enter "1234" in "password-field"
and press "login"
then I will see "welcome"
}
end
Also, in this case I'd be tempted not to implement your common steps as separate steps at all, but to create a single step definition: (assuming Capybara)
Given /^I have logged in$/ do
fill_in 'user-field', :with => 'guest'
fill_in 'password-field', :with => '1234'
click_button 'login'
end
This lends a little bit more meaning to your step definitions, rather than creating a sequence of page interactions which need to be mentally parsed before you realise 'oh, this section is logging me in'.
A better approach is suggested to use ruby level "methods" to code reuse instead of nested steps from code maintenance and debugging perspective.
Here is the link to more detail:
Reuse Cucumber steps
Description
The following method proposes an alternative approach to one of the solutions described in Jon M's answer.
Namely, instead of calling nested steps inside step definitions, such common blocks of steps can be extracted into external .feature files which can be included into your feature file (in a manner of speaking).
How-to
1. Expose utility / helper methods to be able to run steps parsed from a .feature file
# features/support/env.rb
# expose Cucumber runtime
InstallPlugin do |_, registry|
runtime = registry.instance_variable_get('#registry').instance_variable_get('#runtime')
Cucumber.define_singleton_method(:runtime) { runtime }
end
# extend current World with methods to run dynamic (already parsed) steps
Before do
step_invoker = Cucumber::Runtime::SupportCode::StepInvoker.new(Cucumber.runtime.support_code)
define_singleton_method(:dynamic_steps) do |steps|
steps.each do |step|
dynamic_step(step)
end
end
define_singleton_method(:dynamic_step) do |step|
LOGGER.info("Running template step: #{step[:text]}")
step_invoker.step(step)
end
end
2. Create a template file which will contain the steps to be shared
# features/templates/my_profile.template.feature
#template
Feature: Steps to navigate to my_profile_page
Scenario: login_page
Given my app has started on "login_page"
And I enter "guest" in "user-field" on "login_page"
And I enter "1234" in "password-field" on "login_page"
And I press "login" on "login_page" and go to "welcome_page"
Scenario: welcome_page
Given that I am on "welcome_page"
And I click "my_profile_button" on "welcome_page" and go to "my_profile_page"
Scenario: my_profile_page
...
3. Create an utility module which will parse steps from a .feature file
# features/support/template_parser.rb
require 'gherkin/parser'
require 'gherkin/pickles/compiler'
module TemplateParser
class << self
def read_from_template(template_path, from: nil, till: nil)
pickles = load_template(template_path)
flow = construct_flow(pickles)
slice_flow(flow, from, till)
end
private
def load_template(template_path)
source = {
uri: template_path,
data: File.read(template_path),
mediaType: 'text/x.cucumber.gherkin+plain'
}
def source.uri
self[:uri]
end
gherkin_document = Gherkin::Parser.new.parse(source[:data])
id_generator = Cucumber::Messages::IdGenerator::UUID.new
Gherkin::Pickles::Compiler.new(id_generator).compile(gherkin_document, source)
end
def construct_flow(pickles)
pickles.to_h do |pickle|
[
pickle.name,
pickle.steps.map(&:to_h).map { |step| step[:argument] ? step.merge(step[:argument]) : step }
]
end
end
def slice_flow(flow, from, till)
raise NameError, "From step '#{from}' does not exist!" unless from.nil? || flow.keys.include?(from)
raise NameError, "Till step '#{till}' does not exist!" unless till.nil? || flow.keys.include?(till)
from_idx = from.nil? ? 0 : flow.keys.index(from)
till_idx = till.nil? ? -1 : flow.keys.index(till)
flow.slice(*flow.keys[from_idx...till_idx])
end
end
end
4. Create a step definition that will load this template and inject the specified steps dynamically at runtime
And('I complete the {string} template from the {string} until the {string}') do |template, from, till|
template_path = "features/templates/#{template}.template.feature"
flow = TemplateParser.read_from_template(
template_path,
from: from.empty? ? nil : from,
till: till.empty? ? nil : till
)
flow.each_value { |steps| dynamic_steps(steps) }
end
5. Use this step inside your main feature file, by declaring which blocks of steps to use
# features/tests/welcome.feature
Feature: User is welcomed
Scenario: Verify that user sees welcome text
Given I complete the 'my_profile' template from the 'login_page' until the 'my_profile_page'
Then I see 'welcome' on 'welcome_page'
6. Make sure you omit the #template .feature files from being run in your tests
$ bundle exec cucumber --tags ~#template
Limitations
Con:
This method exposes some internals of the private API of cucumber-ruby, which may change in future.
Con:
This is a non-standard way of sharing steps between feature files.
Helper methods are the preferred way to achieve this, as per FAQ.
Pro:
The common blocks of steps are syntax-highlighted, and have proper IntelliSense support in your editor of choice.
Pro:
You can encode entire "workflows" easily this way, allowing you to encode your workflow expectations in a DRY way.
Namely, you can reuse those workflow steps by completing the first part of a workflow, change a few things on a single page as per your test requirements, resume those workflow steps from the follow-up page, and add an appropriate verification at the end of the workflow that covers those test requirements.

Resources