I have to make some operations when a Feature file starts or ends.
But I didn't find any way that Selenium can know it.
Meanwhile I use a specific hook tag to catch the beginning and another one to catch the end. But Is there a way to know it in Selenium code?
You can use before and after hook to perform some actions, you can add extra tag to your cucumber scenario and check it by scenario.getSourceTagNames(). see the example below:
#Before
public void setUpScenario(Scenario scenario) {
List<String> tags = scenario.getSourceTagNames();
if (tags.contains(scenario_specific_tag)) {
System.out.println("Before your scenario running ...." );
}
}
#After
public void endUpScenario(Scenario scenario) {
List<String> tags = scenario.getSourceTagNames();
if (tags.contains(scenario_specific_tag)) {
System.out.println("After your scenario ...." );
}
}
Related
I've been spotting a lot of these in my project's tests:
#Test
void someTest() throws IOException {
if (checkIfTestIsDisabled(SOME_FLAG)) return;
//... the test starts now
Is there an alternative to adding a line at the beginning of each test? For example in JUnit4 there is an old project that provides an annotation #RunIf(somecondition) and I was wondering if there is something similar in JUnit5?
Thank you for your attention.
Tests can be disabled with #DisabledIf and a custom condition.
#Test
#DisabledIf("customCondition")
void disabled() {
// ...
}
boolean customCondition() {
return true;
}
See also the user guide about custom conditions.
String Actualvalue= d.findElement(By.xpath("//[#id=\"wrapper\"]/main/div[2]/div/div[1]/div/div[1]/div[2]/div/table/tbody/tr[1]/td[1]/a")).getText();
Assert.assertEquals(Actualvalue, "jumlga");
captureScreen(d, "Fail");
The assert should not be put before your capture screen. Because it will immediately shutdown the test process so your code
captureScreen(d, "Fail");
will be not reachable
This is how i usually do:
boolean result = false;
try {
// do stuff here
result = true;
} catch(Exception_class_Name ex) {
// code to handle error and capture screen shot
captureScreen(d, "Fail");
}
# then using assert
Assert.assertEquals(result, true);
1.
A good solution will be is to use a report framework like allure-reports.
Read here:allure-reports
2.
We don't our tests to be ugly by adding try catch in every test so we will use Listeners which are using an annotations system to "Listen" to our tests and act accordingly.
Example:
public class listeners extends commonOps implements ITestListener {
public void onTestFailure(ITestResult iTestResult) {
System.out.println("------------------ Starting Test: " + iTestResult.getName() + " Failed ------------------");
if (platform.equalsIgnoreCase("web"))
saveScreenshot();
}
}
Please note I only used the relevant method to your question and I suggest you read here:
TestNG Listeners
Now we will want to take a screenshot built in method by allure-reports every time a test fails so will add this method inside our listeners class
Example:
#Attachment(value = "Page Screen-Shot", type = "image/png")
public byte[] saveScreenshot(){
return ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
}
Test example
#Listeners(listeners.class)
public class myTest extends commonOps {
#Test(description = "Test01: Add numbers and verify")
#Description("Test Description: Using Allure reports annotations")
public void test01_myFirstTest(){
Assert.assertEquals(result, true)
}
}
Note we're using at the beginning of the class an annotation of #Listeners(listeners.class) which allows our listeners to listen to our test, please mind the (listeners.class) can be any class you named your listeners.
The #Description is related to allure-reports and as the code snip suggests you can add additional info about the test.
Finally, our Assert.assertEquals(result, true) will take a screen shot in case the assertion fails because we enabled our listener.class to it.
I am a newbie in automation testing, and m really confused about assert and verify.Since, I am using TestNG, according to my research I came to know that in webdriver, we dont have verify, we have hard and soft assertion. But when I search for it, I get all mixed answers. and nowhere can I find a detailed example.
For soft assertion I saw someone using 'customverification' but when I try to write that in my program I get error, asking to create a class or interface.
Can someone please help me in this. I am studying through internet so its really hard to get correct answers.
Thanks
package revision;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.Test;
public class Six {
WebDriver driver=new FirefoxDriver();
#Test
public void SandyOne() {
driver.get("file:///C:/Users/Sandeep%20S/Desktop/Test.html");
Assert.assertTrue(IsElementPresent(By.xpath("//input[#id='custom']")), "tab was missing");
driver.findElement(By.xpath("//input[#id='custom']")).sendKeys("abcd");
System.out.println("1st program");
System.out.println("blah 1");
System.out.println("blah 2");
}
public boolean IsElementPresent(By by) {
try {
driver.findElements(by);
return true;
} catch (org.openqa.selenium.NoSuchElementException e) {
return false;
}
}
}
If you have an assert that fails the test will be stopped, where for verify the test will be continued and the error will be logged.
Ideally you will have only one assert per test (e.g. the correct page has loaded) and verify will be used to check the information on that page in this case.
Therefore, if the correct page was not loaded, there is no point in checking the stuff on the page is correct.
You can get an idea and a visual example here.
Your test probably fails here:
Assert.assertTrue(IsElementPresent(By.xpath("//input[#id='custom']")), "tab was missing");
because IsElementPresent returns false. One way to avoid that would be:
try {
Assert.assertTrue(IsElementPresent(By.xpath("//input[#id='custom']")), "tab was missing");
driver.findElement(By.xpath("//input[#id='custom']")).sendKeys("abcd");
}
catch (AssertionError ae) {
//ignore
}
However, catching errors is quite ugly code. A better way would be to use WebDriver.findElements(By by) and check if the resulting list is empty or not.
Hard Assertions:Test execution stops as soon as assertion failure found.
Soft Assertions:Test execution continues even if assertion failure found.
e.g. You have 3 assert statements Assert1,Assert2,Assert3
Now if Assert2 fails in case of hard assertion the test will terminate.
In case of soft assertion it will move to next steps in test and then terminate.
You need to instantiate soft assertion as:
SoftAssertions softAssertion = new SoftAssertions();
softAssertion.assertTrue(condition,message)
In your given code snippet hard assertion makes sense since you cannot move to next step to send text until the input box is found.
In given example you don't need to assert element presence. If it's missing the findElement method will throw an error and you will know that it's not there.
If you have elements's Id, use it instead of xpath. This will make the code more readable and faster:
driver.findElement(By.Id("custom")).sendKeys("abcd");
Instead of directly calling the findElement method, it's recommended to use the PageObject pattern and pick elements with annotations, see PageFactory:
public class TestPage {
#FindBy(id = "custom")
WebElement custom;
private WebDriver driver;
public TestPage (WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public TestPage inputCustom(String txt) {
custom.sendKeys(txt);
return this;
}
}
#Test
public void SandyOne() {
// ...
TestPage page = new TestPage(driver);
page.inputCustom("abcd");
// ...
}
I am new to Selenium, While practicing I come up with one issue, I am doing testing for my own application which has been deployed in tomcat server. So after opening my application I am testing validations in one method and page change in one method. Now My point is I am doing both testing for my both methods at same page.
Why do I need to write same code both methods,
driver.get("http://localhost:8070/");
driver.findElement(By.xpath("//div[#id='actions']/div[2]/a/span")).click();
driver.findElement(By.linkText("/ReportGenerator")).click();
How can I directly perform operations, If I remove above two lines in my second method It is getting failed. How to solve this?
#Test
public void analysisValidation()
{
driver.get("http://localhost:8070/");
driver.findElement(By.xpath("//div[#id='actions']/div[2]/a/span")).click();
driver.findElement(By.linkText("/ReportGenerator")).click();
driver.findElement(By.id("Analysis")).click();
WebElement webElement = driver.findElement(By.id("modelForm.errors"));
String alertMsg = webElement.getText();
System.out.println(alertMsg);
Assert.assertEquals("Please select a Survey Id to perform Aggregate Analysis", alertMsg);
}
#Test
public void testAnalysisPage()
{
driver.get("http://localhost:8070/");
driver.findElement(By.xpath("//div[#id='actions']/div[2]/a/span")).click();
driver.findElement(By.linkText("/ReportGenerator")).click();
new Select(driver.findElement(By.id("surveyId"))).selectByVisibleText("Apollo");
driver.findElement(By.id("Analysis")).click();
System.out.println(driver.getTitle());
String pageTitle = driver.getTitle();
Assert.assertEquals("My JSP 'analysis.jsp' starting page", pageTitle);
}
How can I directly perform operations, If I remove above two lines in
my second method It is getting failed. How to solve this
The tests fail because each #Test test is executed independently. The code you remove is needed to initialize the driver and load the page.
You can fix this as follows:
Create a function, setUp() with the #beforemethod annotation. Populate it with the driver initialization and loading-page calls.
Create a function, teardown() with the #AfterMethod annotation. Populate it with the driver cleanup calls.
For example, here is some pseudocode (modify this as per taste)
#BeforeMethod
public void setUp() throws Exception {
driver.get("http://localhost:8070/");
driver.findElement(By.xpath("//div[#id='actions']/div[2]/a/span")).click();
driver.findElement(By.linkText("/ReportGenerator")).click();
}
#AfterMethod
public void teardown() throws Exception {
driver.quit()
}
The advantage of the #BeforeMethod and #AfterMethod annotations is that the code will be run before / after each #Test method executes. You can therefore avoid having to duplicate your code.
I would like to catch any throwable during a Selenium test e.g. in order to make a screenshot. The only solution I could come up with for now is to separately surround the test steps with a try and catch block in every test method as following:
#Test
public void testYouTubeVideo() throws Throwable {
try {
// My test steps go here
} catch (Throwable t) {
captureScreenshots();
throw t;
}
}
I'm sure there is a better solution for this. I would like a higher, more centralized location for this try-catch-makeScreenshot routine, so that my test would be able to include just the test steps again. Any ideas would be greatly appreciated.
You need to declare a TestRule, probably a TestWatcher or if you want to define the rules more explicitly, ExternalResource. This would look something like:
public class WatchmanTest {
#Rule
public TestRule watchman= new TestWatcher() {
#Override
protected void failed(Description d) {
// take screenshot here
}
};
#Test
public void fails() {
fail();
}
#Test
public void succeeds() {
}
}
The TestWatcher anonymous class can of course be factored out, and just referenced from the test classes.
I solved a similar problem using Spring's AOP. In summary:
Declare the selenium object as a bean
Add an aspect using
#AfterThrowing
The aspect can take the screenshot and save it to a
file with a semirandom generated name.
The aspect also rethrows the exception, with the exception message including the filename so you can look at it afterwards.
I found it more helpful to save the HTML of the page due to flakiness of grabbing screenshots.