How to connect Selenium Cucumber results to TestRail using JUnit - selenium

My issue is mainly to know how to populate TestRail results after Cucumber scenarios are run. I'm trying to have the results from my JUnit tests run set on an existing TestRail run. I have the APIClient and APIException as per this project. I then created this JUnit class also copying that same project. Not sure how to proceed now as first time using Cucumber and JUnit. Our project has also a Hooks class and a MainRunner if that helps?
public class Hooks {
public static WebDriver driver;
#Before
public void initializeTest() {
System.out.println("Testing whether it starts before every scenario");
driver = DriverFactory.startDriver();
}
}
import java.io.File;
#RunWith(Cucumber.class)
#CucumberOptions(
features = {"src/test/java/clinical_noting/feature_files/"},
glue = {"clinical_noting.steps", "clinical_noting.runner"},
monochrome = true,
tags = {"#current"},
plugin = {"pretty", "html:target/cucumber",
"json:target/cucumber.json",
"com.cucumber.listener.ExtentCucumberFormatter:target/cucumber-
reports/report.html"}
)
public class MainRunner {
#AfterClass
public static void writeExtentReport() {
Reporter.loadXMLConfig(new File(FileReaderManager.getInstance().getConfigReader().getReportConfigPath()))
;
}
}
Thanks for the help.
Update
Got TestRail to update when running the JUnit tests separately. Still not sure how to do it after the Cucumber scenario is run though? That's how it's working now:
public class JUnitProject {
private static APIClient client = null;
private static Long runId = 3491l;
private static String caseId = "";
private static int FAIL_STATE = 5;
private static int SUCCESS_STATE = 1;
private static String comment = "";
#Rule
public TestName testName = new TestName();
#BeforeClass
public static void setUp() {
//Login to API
client = testRailApiClient();
}
#Before
public void beforeTest() throws NoSuchMethodException {
Method m = JUnitProject.class.getMethod(testName.getMethodName());
if (m.isAnnotationPresent(TestRails.class)) {
TestRails ta = m.getAnnotation(TestRails.class);
caseId = ta.id();
}
}
#TestRails(id = "430605")
#Test
public void validLogin() {
comment = "another comment";
Assert.assertTrue(true);
}
#Rule
public final TestRule watchman = new TestWatcher() {
Map data = new HashMap();
#Override
public Statement apply(Statement base, Description description) {
return super.apply(base, description);
}
#Override
protected void succeeded(Description description) {
data.put("status_id", SUCCESS_STATE);
}
// This method gets invoked if the test fails for any reason:
#Override
protected void failed(Throwable e, Description description) {
data.put("status_id", FAIL_STATE);
}
// This method gets called when the test finishes, regardless of status
// If the test fails, this will be called after the method above
#Override
protected void finished(Description description) {
try {
data.put("comment", comment);
client.sendPost("add_result_for_case/" + runId + "/" + caseId, data);
} catch (IOException e) {
e.printStackTrace();
} catch (APIException e) {
e.printStackTrace();
}
};
};
}
And the annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD) //on method level
public #interface TestRails {
String id() default "none";
}

Working now. Had to add the scenario param inside the before method and do the TestRail connection from there.
#regressionM1 #TestRails(430605)
Scenario: Verify the user can launch the application
Given I am on the "QA-M1" Clinical Noting application
Then I should be taken to the clinical noting page
And
public class Hooks {
private static APIClient client = null;
private static Long runId = 3491l;
private static String caseId = "";
private static int FAIL_STATE = 5;
private static int SUCCESS_STATE = 1;
private static String SUCCESS_COMMENT = "This test passed with Selenium";
private static String FAILED_COMMENT = "This test failed with Selenium";
#Rule
public TestName testName = new TestName();
public static WebDriver driver;
#Before
public void initializeTest() {
client = testRailApiClient();
System.out.println("Testing whether it starts before every scenario");
driver = DriverFactory.startDriver();
}
#After()
public void tearDown(Scenario scenario) {
String caseIdSplit = "";
for (String s : scenario.getSourceTagNames()) {
if (s.contains("TestRail")) {
caseIdSplit = s.substring(11, 17); // Hardcoded for now as all the ids have 6 characters
System.out.println("Testing whether the browser closes after every scenario" + caseIdSplit);
}
}
caseId = caseIdSplit;
Map data = new HashMap();
if (!scenario.isFailed()) {
data.put("status_id", SUCCESS_STATE);
data.put("comment", SUCCESS_COMMENT);
} else if (scenario.isFailed()) {
data.put("status_id", FAIL_STATE);
data.put("comment", SUCCESS_COMMENT);
}
try {
client.sendPost("add_result_for_case/" + runId + "/" + caseId, data);
} catch (IOException e) {
e.printStackTrace();
} catch (APIException e) {
e.printStackTrace();
}
}
}
Update
Wrote a post on this here

Related

How to attach/embed captured screenshots during custom softAssertion into Cucumber Report?

In soft assertion screenshot get captured when softAssertions.assertAll() is called. So to capture screenshots for each soft Assertion failure, created simple CustomAssertion which extends to SoftAssertions and in that override a method name onAssertionErrorCollected().
Below is the sample code.
public class CustomSoftAssertion extends SoftAssertions {
public CustomSoftAssertion() {
}
#Override
public void onAssertionErrorCollected(AssertionError assertionError) {
File file = TestRunner.appiumDriver.getScreenshotAs(OutputType.FILE);
try {
FileUtils.copyFile(file, new File(System.getProperty("user.dir") + File.separator + "ScreenShots" + File.separator + LocalDate.now().format(DateTimeFormatter.ofPattern("MMMM_dd_yyyy")) + File.separator + "demo.png"), true);
} catch (IOException e) {
e.printStackTrace();
}
}
}
In the step definition file:
CustomSoftAssertion softAssertion = new CustomSoftAssertion();
softAssertion.assertThat(isLogin).isTrue();
Above code is working properly. But, how to this captured attach/embed this screenshots into the cucumber report?
Note: For Assertion I am using Assertj library.
You attach scenarios to the report by using scenario.attach. This means you'll have to setup some plumbing to get the scenario into the assertion.
public class CustomSoftAssertion extends SoftAssertions {
private final Scenario scenario;
public CustomSoftAssertion(Scenario scenario) {
this.scenario = scenario;
}
#Override
public void onAssertionErrorCollected(AssertionError assertionError) {
// take screenshot and use the scenario object to attach it to the report
scenario.attach(....)
}
}
private CustomSoftAssertion softAssertion;
#Before
public void setup(Scenario scenario){
softAssertion = new CustomSoftAssertion(scenario);
}
#After // Or #AfterStep
public void assertAll(){
softAssertion.assertAll();
}
#Given("example")
public void example(){
softAssertion.assertThat(isLogin).isTrue();
}

Can I execute multiple test cases in same browser using Selenium

I have multiple usernames and passwords. I need to validate all that test data in one Chrome window. And I need to check whether it's working fine or not. Is it possible? Thanks in advance.
public class Wrappers extends GenericWrappers {
public String browserName;
public String dataSheetName;
protected static WebDriver Browser_Session;
#BeforeSuite
public void beforeSuite() {
startResult();
}
#BeforeTest
public void beforeTest() {
loadObjects();
}
#BeforeMethod
public void beforeMethod() {
test = startTestCase(testCaseName, testDescription);
test.assignCategory(category);
invokeApp("Chrome");
}
#AfterSuite
public void afterSuite() {
endResult();
}
#AfterTest
public void afterTest() {
unloadObjects();
}
#AfterMethod
public void afterMethod() {
endTestcase();
}
#DataProvider(name = "fetchData")
public Object[][] getData() {
return DataInputProvider.getSheet(dataSheetName);
}
}
public class Login extends PEFWrappers {
#Parameters("browser")
#BeforeClass()
public void setValues(String browser) {
browserName = browser;
testCaseName = "TC001 - Login";
testDescription = "Login and Submit a form";
category = "smoke";
dataSheetName = "TC_001";
}
#Test(dataProvider = "fetchData")
public void loginPEF(String LoginId, String Password) throws InterruptedException
{
new LoginPage(driver, test)
.enterLoginID(LoginId)
.enterPassword(Password)
.clickLogin();
}
}
You can specify the set of credentials in the DataProvider method
For eg
#DataProvider(name="fetchData")
public Object[][] getData()
{
Object [][] myData = {{"user1","pwd1"},
{"user2","pwd2"}};
return myData;
}
Here I have given 2 sets of username/Password So the test will be executed 2 times with 2 different sets of credentials.
Here you are taking values from external file. So just enter username and password in rows. Test will repeat as many times as the number of rows available in the datasheet

Unable to run multiple feature files together at once

I want to run multiple feature files first the partyfeatures.feature and next policyfeature.feature , but I am unable to run the second one . Below is my runner class .
#RunWith(Cucumber.class)
#CucumberOptions(features = {"src/test/resources"},
glue = {"com.cucumber.bhsibase.party.tests"})
public class TestRunner {
//runner class
public static WebDriver driver ;
private TestNGCucumberRunner testNGCucumberRunner;
#BeforeClass(alwaysRun = true)
public void setUpClass() throws Exception {
ConfigReader reader = new ConfigReader();
driver = new FirefoxDriver() ;
driver.get(reader.readurls("ExpressURL"));
testNGCucumberRunner = new TestNGCucumberRunner(this.getClass());
}
#Test(description = "Runs Cucumber Feature", dataProvider = "features")
public void feature(CucumberFeatureWrapper cucumberFeature) {
testNGCucumberRunner.runCucumber(cucumberFeature.getCucumberFeature());
}
#DataProvider
public Object[][] features() {
return testNGCucumberRunner.provideFeatures();
}
#AfterClass(alwaysRun = true)
public void tearDownClass() throws Exception {
driver.quit();
testNGCucumberRunner.finish();
}
}

DataStreamer does not work well

I'm using Ignite 2.1.0 and I create a simple program to try DataStreamer, but I offen got error like this:
"[diagnostic]Failed to wait for partition map exchange" or "Attempted to release write lock while not holding it".
I started two local nodes, one was started in windows CMD using example xml configuration and another was started in Eclipse. My code in Eclipse like this :
public class TestDataStreamer {
public static void main(String[] args) {
// TODO Auto-generated method stub
long bgn,end;
IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setPeerClassLoadingEnabled(true);
Ignite ignite = Ignition.start(cfg);
CacheConfiguration<Long, Map> cacheConf = new CacheConfiguration();
cacheConf.setName("TestDataStreamer").setCacheMode(CacheMode.REPLICATED);
cacheConf.setBackups(0);
IgniteCache cache = ignite.getOrCreateCache(cacheConf);
cache.clear();
File dataFile = new File("D:/data/1503307171374.data"); //10,000,000 rows text data
bgn = System.currentTimeMillis();
try {
loadByStreamer(dataFile,ignite,"TestDataStreamer");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
end = System.currentTimeMillis();
System.out.println("---------------");
System.out.println((end-bgn)/1000.0+" s");
}
cache.destroy();
System.out.println("cache destroy...");
ignite.close();
System.out.println("finish");
}
private static void loadByStreamer(File dataFile, Ignite ignite, String cacheName) throws Exception {
IgniteDataStreamer<Long,TestObj> ds = ignite.dataStreamer(cacheName);
//ds.allowOverwrite(true);
ds.autoFlushFrequency(10000);
ds.perNodeBufferSize(4096);
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(dataFile),"UTF-8"));
String line = null;
long count = 0;
while((line=br.readLine())!=null){
ds.addData(System.currentTimeMillis(), parseData(line, Constants.DEFAULT_SEPARATOR,
"id,sn,type_code,trade_ts,bill_ts,company_code,company_name,biz_type,charge_amt,pay_mode".split(",")));
if(++count%10000==0){
System.out.println(count+" loaded...");
}
//System.out.println(count+":"+line);
}
System.out.println("flushing...");
ds.flush();
System.out.println("flushed");
br.close();
ds.close();
System.out.println("file handled...");
}
private static TestObj parseData(String data, String saperator, String[] fields){
TestObj obj = new TestObj();
if(data!=null && saperator.trim().length()>0){
String[] values = data.split(saperator);
obj.setId(values[0]);
obj.setSn(values[1]);
obj.setType_code(values[2]);
obj.setTrade_ts(values[3]);
obj.setBill_ts(values[4]);
obj.setCompany_code(values[5]);
obj.setCompany_name(values[6]);
obj.setBiz_type(values[7]);
obj.setCharge_amt(values[8]);
obj.setPay_mode(values[9]);
}
return obj;
}
}
class TestObj {
private String id;
private String sn;
private String type_code;
private String trade_ts;
private String bill_ts;
private String company_code;
private String company_name;
private String biz_type;
private String charge_amt;
private String pay_mode;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getType_code() {
return type_code;
}
public void setType_code(String type_code) {
this.type_code = type_code;
}
public String getTrade_ts() {
return trade_ts;
}
public void setTrade_ts(String trade_ts) {
this.trade_ts = trade_ts;
}
public String getBill_ts() {
return bill_ts;
}
public void setBill_ts(String bill_ts) {
this.bill_ts = bill_ts;
}
public String getCompany_code() {
return company_code;
}
public void setCompany_code(String company_code) {
this.company_code = company_code;
}
public String getCompany_name() {
return company_name;
}
public void setCompany_name(String company_name) {
this.company_name = company_name;
}
public String getBiz_type() {
return biz_type;
}
public void setBiz_type(String biz_type) {
this.biz_type = biz_type;
}
public String getCharge_amt() {
return charge_amt;
}
public void setCharge_amt(String charge_amt) {
this.charge_amt = charge_amt;
}
public String getPay_mode() {
return pay_mode;
}
public void setPay_mode(String pay_mode) {
this.pay_mode = pay_mode;
}
}
If stop the node started in CMD and run the program in only one node, it works well.
Is there anyone can help me?
Update jdk for both nodes to the same version, for example for 1.8.0_144(as you already have it in installed), or at least, try to update idk in eclipse to the latest of 1.7 versions, it should help.
There is a thread on Ignite user list, when guys faced pretty the same exception and updating of java version helped them to fix it.

Configuring ExtentReports to provide accurate test statuses and screenshot on failure

I am having some difficulty tweaking ExtentReports to provide the desired output.
I have a simple test framework with TestNG, using a TestBase class to do the heavy lifting to keep tests simple. I wish to implement ExtentReports in a simple fashion, using the TestNG ITestResult interface to report Pass, Fail and Unknown.
Here are example tests, 1 pass and 1 deliberate fail:
public class BBCTest extends TestBase{
#Test
public void bbcHomepagePass() throws MalformedURLException {
assertThat(driver.getTitle(), (equalTo("BBC - Home")));
}
#Test
public void bbcHomePageFail() throws MalformedURLException {
assertThat(driver.getTitle(), (equalTo("BBC - Fail")));
}
And here is the relevant section in TestBase:
public class TestBase implements Config {
protected WebDriver driver = null;
private Logger APPLICATION_LOGS = LoggerFactory.getLogger(getClass());
private static ExtentReports extent;
private static ExtentTest test;
private static ITestContext context;
private static String webSessionId;
#BeforeSuite
#Parameters({"env", "browser"})
public void beforeSuite(String env, String browser) {
String f = System.getProperty("user.dir") + "\\test-output\\FabrixExtentReport.html";
ExtentHtmlReporter h = new ExtentHtmlReporter(f);
extent = new ExtentReports();
extent.attachReporter(h);
extent.setSystemInfo("browser: ", browser);
extent.setSystemInfo("env: ", env);
}
#BeforeClass
#Parameters({"env", "browser", "login", "mode"})
public void initialiseTests(String env, String browser, String login, String mode) throws MalformedURLException {
EnvironmentConfiguration.populate(env);
WebDriverConfigBean webDriverConfig = aWebDriverConfig()
.withBrowser(browser)
.withDeploymentEnvironment(env)
.withSeleniumMode(mode);
driver = WebDriverManager.openBrowser(webDriverConfig, getClass());
String baseURL = EnvironmentConfiguration.getBaseURL();
String loginURL = EnvironmentConfiguration.getLoginURL();
APPLICATION_LOGS.debug("Will use baseURL " + baseURL);
switch (login) {
case "true":
visit(baseURL + loginURL);
break;
default:
visit(baseURL);
break;
}
driver.manage().deleteAllCookies();
}
#BeforeMethod
public final void beforeTests(Method method) throws InterruptedException {
test = extent.createTest(method.getName());
try {
waitForPageToLoad();
webSessionId = getWebSessionId();
} catch (NullPointerException e) {
APPLICATION_LOGS.error("could not get SessionID");
}
}
#AfterMethod
public void runAfterTest(ITestResult result) throws IOException {
switch (result.getStatus()) {
case ITestResult.FAILURE:
test.fail(result.getThrowable());
test.fail("Screenshot below: " + test.addScreenCaptureFromPath(takeScreenShot(result.getMethod().getMethodName())));
test.fail("WebSessionId: " + webSessionId);
break;
case ITestResult.SKIP:
test.skip(result.getThrowable());
break;
case ITestResult.SUCCESS:
test.pass("Passed");
break;
default:
break;
}
}
private String takeScreenShot(String methodName) {
String path = System.getProperty("user.dir") + "\\test-output\\" + methodName + ".jpg";
try {
File screenshotFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenshotFile, new File(path));
} catch (Exception e) {
APPLICATION_LOGS.error("Could not write screenshot" + e);
}
return path;
}
#AfterClass
public void tearDown() {
driver.quit();
}
#AfterSuite()
public void afterSuite() {
extent.flush();
}
Here is the report:
The issues are:
The name of the failed test is not recorded at left hand menu
The screenshot is not displayed despite correctly being taken
It is reporting both a Pass and Unexpected for the passed test
Version 3.0
Most of code is provided by person created this library, i just modified to your needs.
public class TestBase {
private static ExtentReports extent;
private static ExtentTest test;
#BeforeSuite
public void runBeforeEverything() {
String f = System.getProperty("user.dir")+ "/test-output/MyExtentReport.html";
ExtentHtmlReporter h = new ExtentHtmlReporter(f);
extent = new ExtentReports();
extent.attachReporter(h);
}
#BeforeMethod
public void runBeforeTest(Method method) {
test = extent.createTest(method.getName());
}
#AfterMethod
public void runAfterTest(ITestResult result) {
switch (result.getStatus()) {
case ITestResult.FAILURE:
test.fail(result.getThrowable());
test.fail("Screenshot below: " + test.addScreenCaptureFromPath(takeScreenShot(result.getMethod().getMethodName())));
break;
case ITestResult.SKIP:
test.skip(result.getThrowable());
break;
case ITestResult.SUCCESS:
test.pass("Passed");
break;
default:
break;
}
extent.flush();
}
protected String takeScreenShot(String methodName) {
String path = "./screenshots/" + methodName + ".png";
try {
File screenshotFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenshotFile, new File(path));
} catch (Exception e) {
APPLICATION_LOGS.error("Could not write screenshot" + e);
}
return path;
}
}
You need several changes to make. Instantiate the ExtentReport & add configuration information in any of the configuration methods except BeforeClass.
#BeforeTest
#Parameters({"env", "browser"})
public void initialiseTests(String env, String browser, String emulatorMode, String mode) {
EnvironmentConfiguration.populate(env);
WebDriverConfigBean webDriverConfig = aWebDriverConfig()
.withBrowser(browser)
.withDeploymentEnvironment(env)
.withSeleniumMode(mode);
driver = WebDriverManager.openBrowser(webDriverConfig, getClass());
APPLICATION_LOGS.debug("Will use baseURL " + EnvironmentConfiguration.getBaseURL());
try {
visit(EnvironmentConfiguration.getBaseURL());
} catch (MalformedURLException e) {
e.printStackTrace();
}
driver.manage().deleteAllCookies();
}
Initailize test = extent.startTest(testName); in the #BeforeMethod section.
#BeforeMethod
public void beforeM(Method m) {
test = extent.startTest(m.getName());
}
And, you may call extent.endTest(test); in the #AfterTest method.
#AfterTest
public void afterTests() {
extent.endTest(test);
extent.close();
}
}
And, to log your step info call test.log(LogStatus, "your info to show"); with appropirate status.