Screenshot with Cucumber Groovy - cucumber

I am working with Cucumber features and Groovy as Step definitions in Katalon Studio. As we have each step in the step definition and wanted to take a screenshot when the step is failed (AShot or whatever). I would like to have the code to take the snap and would like to know do we need this in each step definition file.
I saw this similar question in this forum but does not have a clear answer.
Please note that I know the option in “Take Screenshot when execution failed” in settings.
Can you please provide the sample on this to proceed further?

Try adding the following to your #After test hook (or Test Listeners):
#After
public void TearDown(Scenario scenario) {
if (scenario.isFailed()) {
WebDriver driver = DriverFactory.getWebDriver()
byte[] screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
scenario.embed(screenshot, "image/png");
scenario.write(scenario.getName());
}
}
You will need some imports:
import cucumber.api.Scenario;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import com.kms.katalon.core.webui.driver.DriverFactory;
(Or just pres Ctrl + Shift + O to automatically import the missing classes.)

1st you are planning to run as a test suite of your test pack, you don't need to add any code to capture screenshots, Katalon will automatically do that.
for running as a test case use below example
public void catchNotyMessage(){
TestObject noty_warning = WebUI.modifyObjectProperty(findTestObject("DUMMY"), 'css', 'equals', 'div.noty_type_warning', true)
TestObject noty_error = WebUI.modifyObjectProperty(findTestObject("DUMMY"), 'css', 'equals', 'div.noty_type_error', true)
if (WebUI.verifyElementPresent(noty_error, 1, FailureHandling.OPTIONAL)){
this.takeWebElementScreenshot(noty_error)
}
else if (WebUI.verifyElementPresent(noty_warning, 1, FailureHandling.OPTIONAL)){
this.takeWebElementScreenshot(noty_warning)
}
}

Related

Dagger2 ApplicationComponent not generated(git project included)

So I'm trying to follow Googles architecture example and my daggerappcomponent is not generating. I tried changing up the gradle files but I'm not sure what I'm doing wrong. First time doing something "advanced" like this(for me at least). I commented out everything from the DI package as I cannot get it working without the QuoteApplication, and I cant get QuoteApplication working without building the project and hoping it will generate necessary dagger files.
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerApplicationComponent.factory().create(applicationContext) //here is the problem
}
Here's the project https://github.com/Nikola-Milovic/QuoteAppMvvm
I tried a lot of different build gradles and I tried cleaning rebuidling and so on. I've read all of the online fixes but nothing has worked. I'm certain it's my fault but it might be a bug or something. My last resort is to ask here. Kinda stuck at this.
It worked perfeclty fine for me.
I build.
The component is generated.
The buld fails because no import.
I import the newly created component. (import com.example.quoteappmvvm.di.DaggerApplicationComponent)
It works.
package com.example.quoteappmvvm
import com.example.quoteappmvvm.di.DaggerApplicationComponent >>>> You need this!!!
import dagger.android.AndroidInjector
import dagger.android.support.DaggerApplication
//open class QuoteApplication{
//// override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
////
//// return DaggerApplicationComponent.factory().create(applicationContext)
//// }
//
//// override fun onCreate() {
//// super.onCreate()
//// // if (BuildConfig.DEBUG) Timber.plant(DebugTree())
//// }
//}
open class QuoteApplication : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerApplicationComponent.factory().create(this)
}
override fun onCreate() {
super.onCreate()
// if (BuildConfig.DEBUG) Timber.plant(DebugTree())
}
}

How to access TestNg parameters from Cucumber Scenario file (Change the scenario Name Dynamically)

Currently, I have implemented cucumber runner level parallel project using TestNG + Cucumber and it works really well. We are using allure for report generation but when I run the test cases in parallel imaging in 2 devices report will get replace since my scenario name is not unique in the feature file. Now I want to make my Scenario name dynamic so I want to put the Device name and Os version which I got from TestNg params function and access it in the Feature file. Here is my Runner file where I get parameters.
import org.testng.annotations.BeforeTest;
import cucumber.api.java.Before;
import org.testng.annotations.Parameters;
import cucumber.api.CucumberOptions;
import cucumber.api.testng.AbstractTestNGCucumberTests;
import device.Device;
import device.DeviceFactory;
import gherkin.formatter.model.Scenario;
#CucumberOptions(plugin = { "pretty", "html:target/html/", "json:target/cucumber.json", "junit:TEST-all.xml" }, glue = {
"steps" }, tags = { "#Mobile" })
public class ParallelRunner extends AbstractTestNGCucumberTests {
#BeforeTest
#Parameters({ "deviceName", "platformVersion" })
public void executeParallelTests(String deviceName, String platformVersion) {
Device device = new Device();
device.setDeviceName(deviceName);
device.setOsVersion(platformVersion);
DeviceFactory.setDevice(device);
}
}
I want to achieve something like this in my feature file
Feature: SignUp
#Android #IOS #Mobile
Scenario: SignUp ${"eviceName"} ${"platformVersion"}
Can anyone let me know how this can be achieved in cucumber?

My first basic Cucumber program (Scenario) fails - Java

I wrote my first Cucumber program today, and it fails. I wrote a very basic one, a simple scenario and it's step definition. Below is the feature file code and the step definition code.
Step Definiton code:
import cucumber.api.java.en.When;
import cucumber.api.java.en.Then;
public class Testing_Example1 {
#When("^I am on x page$")
public void i_am_on_x_page() throws Throwable {
System.out.println("I am on xPage");
}
#Then("^I see that element$")
public void i_see_that_element() throws Throwable {
System.out.println("I can see that page");
}
}
Feature File Code:
Feature: Testing
Scenario: s1
When I am on x page
Then I see that element
I have added the system variables as well - The JAVA_HOME and the maven variables as well and linked it to the PATH variable I system variables.
I have added dependencies in the POM file, such as the Cucumber-Java, Cucumber-Junit and for selenium as well and yet my program fails and says the steps are undefined.
Output:
1 Scenarios (1 undefined)
2 Steps (2 undefined)0m0.000s
You can implement missing steps with the snippets below:
#When("^I am on x page$")
public void i_am_on_x_page() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Then("^I see that element$")
public void i_see_that_element() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
Undefined step: When I am on x page
Undefined step: Then I see that element
Process finished with exit code 0
I guess it's because my feature file is not getting linked with the step definition file, but I don't understand what is missing that the feature file does not execute properly and scenarios fail. Someone who has knowledge about this, do help.
Thank You!
I found the solution to this. I just edited the configuration of the feature file - > edit configurations -> Paste the path of the package in which your step definition file is present -> apply.
I just has to link the feature file to the step definition using Glue.
Specify the stepdefintion & feature file details in your cucumber runner class.
#CucumberOptions(
plugin={"pretty", "html:target/cucumber-html-report","json:target/cucumber-report.json"},
features = "src/test/resources",
glue ="com.vg.pw.ui.stepdefinitions",
)
public class CucumberRunner {
...
}

Custom update listener to set subtask's fix-version

I'm developing custom listener which will update subtask's fix version to same value as it's parent issue.
Currently we are using post-function in workflow in order to set subtask's fix version according to parent on subtask creation. This however doesn't cover cases when subtask already exists and parent's fix version gets updated. New value from parent task is not propagated to subtask.
I'm using script runner and I'm creating 'Custom lisatener', for my specific project and specified Event: 'Issue Updated'. I added script as following:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.config.SubTaskManager
import com.atlassian.jira.event.issue.AbstractIssueEventListener
import com.atlassian.jira.event.issue.IssueEvent
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.project.version.Version
import org.apache.log4j.Logger
class CopyFixVersionFromParentToChild extends AbstractIssueEventListener {
Logger log = Logger.getLogger(CopyFixVersionFromParentToChild.class);
SubTaskManager subTaskManager = ComponentAccessor.getComponent(SubTaskManager.class)
IssueManager issueManager = ComponentAccessor.getComponent(IssueManager.class)
#Override
void issueUpdated(IssueEvent event) {
log.warn("\nIssue updated!!!\n")
try {
Issue updatedIssue = event.getIssue()
if (updatedIssue.issueTypeObject.name == "Parent issue type") {
Collection<Version> fixVersions = new ArrayList<Version>()
fixVersions = updatedIssue.getFixVersions()
Collection<Issue> subTasks = updatedIssue.getSubTaskObjects()
if (subTaskManager.subTasksEnabled && !subTasks.empty) {
subTasks.each {
if (it instanceof MutableIssue) {
((MutableIssue) it).setFixVersions(fixVersions)
issueManager.updateIssue(event.getUser(), it, EventDispatchOption.ISSUE_UPDATED, false)
}
}
}
}
} catch (ex) {
log.debug "Event: ${event.getEventTypeId()} fired for ${event.issue} and caught by script 'CopyVersionFromParentToChild'"
log.debug(ex.getMessage())
}
}
}
Problem is, that it doesn't work. I'm not sure whethe rit's problem that my script logic is encapsulated inside class. Do I have to register this in some specific way? Or am I using script runner completely wrong and I'm pasting this script to wrong section? I checked code against JIRA API and it looks like it should work, my IDE doesnt show any warnings/errors.
Also, could anyone give me hints on where to find logging output from custom scripts like this? Whatever message I put into logger, I seem to be unable to find anywhere in JIRA logs (although I'm aware that script might not work for now).
Any response is much appreciated guys, Thanks.
Martin
Well, I figure it out.
Method I posted, which implements listener as groovy class is used in different way than I expected. These kind of script files were used to be located in to specific path in JIRA installation and ScriptRunner would register them into JIRA as listeners.
In in order to create 'simple' listener script which reacts to issue updated event, I had to strip it down to this code
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.project.version.Version
IssueManager issueManager = ComponentAccessor.getComponent(IssueManager.class)
Issue updatedIssue = event.getIssue()
Collection<Version> fixVersions = new ArrayList<Version>()
fixVersions = updatedIssue.getFixVersions()
Collection<Issue> subTasks = updatedIssue.getSubTaskObjects()
subTasks.each {
if (it instanceof MutableIssue) {
((MutableIssue) it).setFixVersions(fixVersions)
issueManager.updateIssue(event.getUser(), it, EventDispatchOption.ISSUE_UPDATED, false)
}
}
You past this to script runner interface and it works :-). Hope this helps anyone who's learning ScriptRunner. Cheers.
Matthew

How to Report Results to Sauce Labs using Geb/Spock?

I want to use the Sauce Labs Java REST API to send Pass/Fail status back to the Sauce Labs dashboard. I am using Geb+Spock, and my Gradle build creates a test results directory where results are output in XML. My problem is that the results XML file doesn't seem to be generated until after the Spock specification's cleanupSpec() exits. This causes my code to report the results of the previous test run, rather than the current one. Clearly not what I want!
Is there some way to get to the results from within cleanupSpec() without relying on the XML? Or a way to get the results to file earlier? Or some alternative that will be much better than either of those?
Some code:
In build.gradle, I specify the testResultsDir. This is where the XML file is written after the Spock specifications exit:
drivers.each { driver ->
task "${driver}Test"(type: Test) {
cleanTest
systemProperty "geb.env", driver
testResultsDir = file("$buildDir/test-results/${driver}")
systemProperty "proj.test.resultsDir", testResultsDir
}
}
Here is the setupSpec() and cleanupSpec() in my LoginSpec class:
class LoginSpec extends GebSpec {
#Shared def SauceREST client = new SauceREST("redactedName", "redactedKey")
#Shared def sauceJobID
#Shared def allSpecsPass = true
def setupSpec() {
sauceJobID = driver.getSessionId().toString()
}
def cleanupSpec() {
def String specResultsDir = System.getProperty("proj.test.resultsDir") ?: "./build/test-results"
def String specResultsFile = this.getClass().getName()
def String specResultsXML = "${specResultsDir}/TEST-${specResultsFile}.xml"
def testsuiteResults = new XmlSlurper().parse( new File( specResultsXML ))
// read error and failure counts from the XML
def errors = testsuiteResults.#errors.text()?.toInteger()
def failures = testsuiteResults.#failures.text()?.toInteger()
if ( (errors + failures) > 0 ) { allSpecsPass = false }
if ( allSpecsPass ) {
client.jobPassed(sauceJobID)
} else {
client.jobFailed(sauceJobID)
}
}
}
The rest of this class contains login specifications that do not interact with SauceLabs. When I read the XML, it turns out that it was written at the end of the previous LoginSpec run. I need a way to get to the values of the current run.
Thanks!
Test reports are generated after a Specification has finished execution and the generation is performed by the build system, so in your case by Gradle. Spock has no knowledge of that so you are unable to get that information from within the test.
You can on the other hand quite easily get that information from Gradle. Test task has two methods that might be of interest to you here: addTestListener() and afterSuite(). It seems that the cleaner solution here would be to use the first method, implement a test listener and put your logic in afterSuite() of the listener (and not the task configuration). You would probably need to put that listener implementation in buildSrc as it looks like you have a dependency on SauceREST and you would need to build and compile your listener class before being able to use it as an argument to addTestListener() in build.gradle of your project.
Following on from erdi's suggestion, I've created a Sauce Gradle helper library, which provides a Test Listener that parses the test XML output and invokes the Sauce REST API to set the pass/fail status.
The library can be included by adding the following to your build.gradle file:
import com.saucelabs.gradle.SauceListener
buildscript {
repositories {
mavenCentral()
maven {
url "https://repository-saucelabs.forge.cloudbees.com/release"
}
}
dependencies {
classpath group: 'com.saucelabs', name: 'saucerest', version: '1.0.2'
classpath group: 'com.saucelabs', name: 'sauce_java_common', version: '1.0.14'
classpath group: 'com.saucelabs.gradle', name: 'sauce-gradle-plugin', version: '0.0.1'
}
}
gradle.addListener(new SauceListener("YOUR_SAUCE_USERNAME", "YOUR_SAUCE_ACCESS_KEY"))
You will also need to output the Selenium session id for each test, so that the SauceListener can associate the Sauce Job with the pass/fail status. To do this, include the following output in the stdout:
SauceOnDemandSessionID=SELENIUM_SESSION_ID

Resources