Is it not possible to have both SUCCCESS and FAILURE Outcome in the story?
Lifecycle:
After:
Outcome: FAILURE
Given I capture page screenshot
Given I close browser
Outcome: SUCCESS
Given I close browser
Scenario: Sample one
Given I open browser
When I do something
Scenario: Sample two
Given I open browser
When I do another thing
For example, for failures I want to take a screenshot before closing the browser. If successful I just want to close the browser.
I know I can just close the browser at the end of all my scenarios and only have the failure outcome remain. I would like to know if there is a way to do this in the Lifecycle After.
Thanks.
Quoting OP:
For example, for failures I want to take a screenshot before closing the browser. If successful I just want to close the browser.
Now, the interesting question will be which framework are you using for your assertions?
I'll assume you use Junit which comes bundled with JBehave as JBehave relies on knowing there is an error by JUnit's thrown exception.
The idea is to:
a) throw an exception when an error occurs (so need to check on every step)
b) take a screenshot
c) continue with testing (i.e. closing the browser)
So in order to throw an exception, you really do no need to do much as this is done automatically when using JUnit's Assert statement.
so for example
Assert(username.equals("expected_user").isTrue();
If the above fails an exception will be thrown.
You can capture it as such:
public class RunnerExtension implements AfterTestExecutionCallback {
#Override
public void afterTestExecution(ExtensionContext context) throws Exception {
Boolean testResult = context.getExecutionException().isPresent();
System.out.println(testResult); //false - SUCCESS, true - FAILED
}
}
#ExtendWith(RunnerExtension.class)
public abstract class Tests {
}
Taken from this answer:
JUnit5 - How to get test result in AfterTestExecutionCallback
So basically you override the standard behaviour -after- each assertion has been executed. In the case above you can add (when an exception is thrown --> take screenshot).
Here is the take a screenshot code for Selenium-Java:
WebDriver driver = new FirefoxDriver();
driver.get("http://www.google.com/");
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
// Now you can do whatever you need to do with it, for example copy somewhere
FileUtils.copyFile(scrFile, new File("c:\\tmp\\screenshot.png"));
Hope the above helps!
Related
I have a PageObject startPage where I have a login and a logout method. The login method works fine and is executed in the #BeforeScenario:
#BeforeScenario
public void login() {
// {..} Declaration of baseUrl,user,password...
homeVM.setDefaultBaseUrl(baseUrl);
homeVM.open();
homeVM.login(user, password);
}
and login(user,password) in class homeVM is like:
typeInto(find(By.id(getUserFieldId())), user);
typeInto(find(By.id(getPasswordFieldId())), password);
findBy(getLoginButtonXPath()).then().click();
so nothing special, this works all fine.
Then I switch through several PageObjects in different test steps without a problem. When code reaches the #AfterScenario which looks like:
#AfterScenario
public void logout() {
homeVM.logoff();
}
and class homeVM with method logoff() looks like:
WebElement btnLogout = getDriver().findElement(By.xpath("//a [contains(#class,'lnkLogout')]"));
btnLogout.click();
But this isn't working (nothing happens, no exception, no click.. just nothing). Then I tried to log some information about getDriver() with:
System.out.println("WindowHandles:"+getDriver().getWindowHandles().size());
System.out.println("Title: "+getDriver().getTitle());
and both values are just empty (""). So it seems that getDriver() is just empty (not even null, so I don't get a NullPointerException). Why is it so? I tried to check getDriver() for the last PageObject I used in my test but there I get all the information I need, just getDriver() in the #AfterScenario is empty. Any idea or solution what to do next or why this is happening? I'm using chromeDriver.
EDIT:
Okay, I recognized something unexpected:
I have an assertThat(<something>) method in my last step and this step is actually producing an assignment failure (because the behaviour is not implemented yet)... and if I comment this assertThat() out, the #AfterScenario and its logout is executed correctly. So the webDriver gets "emptied" if the test fails? Is this on purpose?
EDIT2:
If I catch the AssertionErrorException Exception the test runs fine again but of course the test will be marked as "Test Passed". So it really has something to do that if the exception is thrown the current webDriver gets emptied. But this seems to be wrong...
Once Serenity (or Thucydides in this case) spots a test failure (e.g. from an assertion error), the test is switched to "dry-run" mode, as it considers that subsequent steps are compromised and may result in unnecessary (and slow) web driver calls.
As I found out from John Smart that once Serenity spots a test failure the test is switched to "dry-run" mode, so no web driver calls are possible anymore I had to find another way to perform a logout.
As my chromedriver runs by default all scenarios in the same session and browser I had to perform a manual logout after every scenario. But by setting
System.setProperty("restart.browser.each.scenario", "true");
it was possible to restart the browser and clean the session after every scenario. This worked for me so I don't need the #AfterScenario with logoff(); anymore.
overcoming the issue in cucumber watir framework
filename = DateTime.now.strftime("%Y-%m-%d--%Hh_%Mm_%Ss")
#browser.driver.save_screenshot ("#{filename}.png")
Note:
filename is the name of the screenshot file
you can pass the location of the screenshot file as well like this
#browser.driver.save_screenshot ("/Screenshots/#{filename}.png")
I have created a automation suite in java selenium using testng frame work.Basically in my suite the scenarios are placed in between before and after method.
I want to take the screen shot for each failed and passed test scenario.For that i have created a separate class and calling it in each script to capture the screenshot before the after Method.
The issue that i am facing here is if the scenario is getting failed the script stopped executing and it is not moving to the take screenshot line of code and so it is not capturing the screenshot for the failed ones.
So i want the take screenshot program to be only placed in after method so before the driver quit it will take the screenshot inspite of the scenario result of pass/fail.
I have written code for nearly 20 scenario using testng.
Can some one tel me the code in the after method only to take the screenshot without so much effecting the code which i have written.
The screenshot program should only be in the after method so it will capture teh screen before driver quit.
Make sure you catch exceptions so you won't exit the code prematurely.
For example, this is how I take screenshots after every test run (passed or failed). I use the exception value (if any) to dynamically name the screenshot files.
First, an example test method:
[DataSource("System.Data.SqlClient", "Data Source=DEV338\\X2B;Initial Catalog=SeleniumDb;Integrated Security=True",
"dbo.F_single_ErkenningAannemerKlasse1", DataAccessMethod.Sequential), TestMethod]
public void erkenningAannemerKlasse1()
{
try
{
frontUser.erkenningAannemerKlasse1(data);
}
catch (Exception e)
{
exception = e.Message + " " + e.StackTrace;
}
}
Then this method executes after every test. Default behaviour in Microsoft UnitTest framework, in this case.
[TestCleanup()]
public void Cleanup()
{
frontUser.takeScreenshot(data.get("testnaam"), data.get("datarow"), exception);
frontUser.closeBrowser();
}
i have a form filling script
during the execution in any line (Step) if the test case is failed it is directly closing the browser .
ex: while filling the form if it couldn't find a element (Textbox or Checkbox) it throws an exception nosuchelements and directly closes the browser i am using assert (testNG) in my script
what i want is if the test case is failed anywhere middle i want the test case to continue its execution but in the report it should show that the test case is failed
in my code
String Jobvalue = driver.findElement(By.xpath("//label[#for='ctl00_ContentPlaceHolder1_RadPanelBar1_i0_chkColumns_5']")).getText();
Assert.assertEquals(Jobvalue, "Job Value ($)");
Reporter.log(Jobvalue+" Text Verification ---- Passed",true);
Assert will fail the test case if actual value is not equals to expected value
i want an alternate to assert or any code which continues executing the test case till the end and at reports it should show it is failed if the actual value is not equal to expected value
Santhosh, We need more info/code on what are you exactly trying.By assumption, here is my answer for your question.
Use validate() methods rather assert () in your test steps.
Any exception can be easily handled using try-catch.
try{
String Jobvalue = driver.findElement(By.xpath("//label[#for='ctl00_ContentPlaceHolder1_RadPanelBar1_i0_chkColumns_5']")).getText();
Assert.assertEquals(Jobvalue, "Job Value ($)");
}
catch()
{
//Write your code here about failing the test
}
If an Assert fails, it throws an AssertionError and that's why your program is stopped. You can use try/catch to handle the exception.
try{
Assert......
}catch(AssertionError e){
//handle the exception
}
Refer here for Assert documentation
I need to test a webpage via desktop application, I'm trying to use
the selenium IDE, I had sucess to create the test cases, but I'm not
able to execute them on java.
I've been looking for something helpful, but I can't find any help at all.
Thank you
A framework that has been created for just this cause, (it's in Java) can be downloaded here or you can check the project out from github here.
This project was designed to be very simple, yet very effective. This type of framework is a "free version" of my interpretation of a framework that I use every day in production-type environments.
There is a sample test that is enclosed in the project named SampleFunctionalTest.java. Assuming you follow the ReadMe to the T, you should have no problem getting started.
Here is what a test would look like in this framework.
#Config(url = "http://ddavison.github.io/tests/getting-started-with-selenium.htm", browser = Browser.FIREFOX) // You are able to specify a "base url" for your test, from which you will test. You may leave `browser` blank.
public class SampleFunctionalTest extends AutomationTest {
/**
* You are able to fire this test right up and see it in action. Right click the test() method, and click "Run As... jUnit test".
*
* The purpose of this is to show you how you can continue testing, just by taking the semi colon out, and continuing with your test.
*/
#Test
public void test() {
// click / validateAttribute
click(props.get("click"))
.validateAttribute(props.get("click"), "class", "success") // validate that the class indeed added.
// setText / validateText
.setText(By.id("setTextField"), "woot!")
.validateText(By.id("setTextField"), "woot!") // validates that it indeed set.
// check / uncheck
.check(By.id("checkbox"))
.validateChecked(By.id("checkbox")) // validate that it checked
.check(props.get("radio.2")) // remember that props come from <class name>.properties, and are always CSS selectors. (why use anything else, honestly.)
.validateUnchecked(props.get("radio.1")) // since radio 1 was selected by default, check the second one, then validate that the first radio is no longer checked.
// select from dropdowns.
.selectOptionByText(By.xpath("//select[#id='select']"), "Second") // just as a proof of concept that you can select on anything. But don't use xpath!!
.validateText(By.id("select"), "2") // validateText() will actually return the value="" attr of a dropdown, so that's why 2 works but "Second" will not.
.selectOptionByValue(By.cssSelector("select#select"), "3")
.validateText(props.get("select"), "3")
// frames
.switchToFrame("frame") // the id="frame"
.validatePresent(By.cssSelector("div#frame_content"))
// windows
.switchToWindow("Getting Started with Selenium") // switch back to the test window.
.click(By.linkText("Open a new tab / window"))
.waitForWindow("Google") // waits for the url. Can also be the you are expecting. :) (regex enabled too)
.setText(By.name("q"), "google!")
.closeWindow(); // we've closed google, and back on the getting started with selenium page.
}
}
You should create an instance of a WebDriver and call methods on the instance of that object.
An easy example is shown here: http://www.seleniumhq.org/docs/03_webdriver.jsp#introducing-the-selenium-webdriver-api-by-example
I hope you have created the script in webdriver.
Now in the script recorded by the selenium ide you have three methods called
setup, testSomeName and tearDown.
From the very basic: to run this script all you need to do is create a main method in the same class and in that you need to call these methods in the same order as specified above.
After that you just need to run that program.
Here is an example to make it more clear:
public class p_adjcb {
public void setUp() throws Exception {
}
public void testP_adjcb() throws Exception {
}
public void tearDown() throws Exception {
}
public static void main(String[] args) {
p_adjcb obj = new p_adjcb();
try {
obj.setUp();
obj.testP_adjcb();
obj.tearDown();
} catch (Exception ex) {
}
}
}
If you get any compiler error make sure you have downloaded the selenium-standalone-server.jar file and added it to your class path.
This is a very basic start. Later on you may need to use som framework like junit.
Hope it helps.
I'm quite new to WebDriver and TestNG framework. I've started with a project that does a regression test of an e-commerce website. I'm done with the login and registration and so on. But there is something that I don't quite understand.
Example, I have this easy code that searches for a product.
driver.get(url + "/k/k.aspx");
driver.findElement(By.id("q")).clear();
driver.findElement(By.id("q")).sendKeys("xxxx"); //TODO: Make this dynamic
driver.findElement(By.cssSelector("input.submit")).click();
Now I want to check if xxxx is represented on the page. This can be done with
webdriver.findElement(By.cssSelector("BODY")).getText().matches("^[\\s\\S]*xxxxxx[\\s\\S]*$")
I store this in a Boolean and check if its true or false.
Now to the question, based on this Boolean value I want to say that the test result is success or fail. How can I do that? What triggers a testNG test to fail?
TestNG or any other testing tool decides success or failure of a test based on assertion.
Assert.assertEquals(actualVal, expectedVal);
So if actualVal and expectedVal are same then test will pass else it will fail.
Similarly you will find other assertion options if you using any IDE like Eclipse.
If you want to stop your test execution based on the verification of that text value, then you can use Asserts. However, if you want to log the outcome of the test as a failure and carry on, you should try using soft assertions, which log the verification as passed or failed and continue with the test. Latest Testng comes equipped to handle this - info at Cedric's blog
write this code where your if condition fails
throw new RuntimeException("XXXX not found: ");
u can use throw exception, and each method which will cal this meth should also throw Excetion after method name or you can use try catch. sample:
protected Boolean AssertIsCorrectURL(String exedctedURL) throws Exception {
String errMsg = String.format("Actual URL page: '%s'. Expected URL page: '%s'",
this.driver.getCurrentUrl(), exedctedURL);
throw new Exception(errMsg);
}
You can do this.
boolean result = webdriver.findElement(By.cssSelector("BODY")).getText().matches("^[\s\S]xxxxxx[\s\S]$")
Assert.assertTrue(result);