Seems I'm not enough smart to figure it out by myself - I have Eclipse Kepler installed, with jUnit 4.11, selenium-java 2.41 and a mozilla plugin for selenium.
Everything is great, everything (at this moment) works great.
My aim is to create a test, that repeats n times, everytime using the second String[] array element. For example:
`#Test
public void testGoogleSearch() throws Exception {
driver.get(baseUrl);
driver.findElement(By.id("gbqfq")).clear();
driver.findElement(By.id("gbqfq")).sendKeys("Find me"); // Input text from String array here
driver.findElement(By.id("gbqfb")).click();
try {
assertEquals("Find me", driver.findElement(By.id("gbqfq")).getAttribute("value"));
} catch (Error e) {
verificationErrors.append(e.toString());
}
}`
As you can see, there is static "Find me" text. I want, that my test will run 5 times, each time input changes to early defined array elements.
How can i do that? Any clues? I've read about parametrized testing, but does it really is that i need? I didn't found anything there about multiple repeating.
Any help would be great. Thank you.
I've read about parametrized testing, but does it really is that i
need?
Yes, it is exactly what you need. Parameterized.class:
#RunWith(Parameterized.class)
public class GoogleSearchClass {
private String searchString;
private String expectedString;
public GoogleSearchClass (String srch, String expect){
searchString = srch;
expectedString = expect;
}
#Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{"search1", "expected1"}, {"search2", "expected2"}, {"search3", "expected3"}
});
}
#Test
public void testGoogleSearch() throws Exception {
driver.get("http://google.com");
driver.findElement(By.id("gbqfq")).clear();
driver.findElement(By.id("gbqfq")).sendKeys(searchString); // Input text from String array here
driver.findElement(By.id("gbqfb")).click();
try {
// Assert.assertEquals(expectedString, driver.findElement(By.id("gbqfq")).getAttribute("value"));
} catch (AssertionError e) {
}
}
}
Related
In Selenium, if a step fails for a test case, is it possible to just report the failure and continue with remaining steps? Currently the execution halts if there is an exception. This is what my Test case looks like-
public class TC002_abc extends OpentapWrappers
{
#Test (description="Test")
public void main()
{
try
{
WebDriverWait wait=new WebDriverWait(driver, 60);
VerifyTitle(Constant.HomePage_Title);
Click(HomePage.link_Login(driver), "Login Link");
wait.until(ExpectedConditions.urlContains(Constant.LoginURL));
VerifyTextPopulated(CommunicationPref.lbl_EmailAddress_Input(driver), Constant.EmailAddress);
/* Validate Email Communications */
Click(CommunicationPref.link_EditEmailCommunications(driver),"Edit Email Communications");
VerifyText(CommunicationPref.lbl_UnCheckedEmailCommunications(driver), Constant.UnCheckedEmailCommunications_Text);
Click(CommunicationPref.btn_EmailCommunicationsSave(driver), "Save");
VerifyText(CommunicationPref.lbl_CheckedEmailCommunications(driver), Constant.CheckedEmailCommunications_Text);
}
catch (NoSuchElementException e)
{
e.printStackTrace();
Reporter.reportStep("NoSuchElementException" , "FAIL");
}
}
#BeforeClass
public void beforeClass()
{
browserName="firefox";
testCaseName = "TC002_abc";
testDescription = "Test";
}
}
Sample Method-
public static void VerifyTitle(String title){
try
{
if (driver.getTitle().equalsIgnoreCase(title))
{
Reporter.reportStep("Page is successfully loaded :"+title, "PASS");
}
else
Reporter.reportStep("Page Title :"+driver.getTitle()+" did not match with :"+title, "FAIL");
}
catch (Exception e)
{
e.printStackTrace();
Reporter.reportStep("The title did not match", "FAIL");
}
}
Since you're using TestNG, implement a Soft Assertion
public void VerifyTitle(String title)
{
SoftAssert assertion = new SoftAssert();
String returnedTitle = driver.getTitle();
if (assertion.assertTrue(returnedTitle.contains(title)))
{
Reporter.reportStep("Page is successfully loaded :" + title, "PASS");
} else
{
Reporter.reportStep("Page Title :" + driver.getTitle() + " did not match with :" + title, "FAIL");
}
}
Let me know if this helps.
if a step fails for a test case, is it possible to just report the
failure and continue with remaining steps?
Short answer: YES
Long answer: YES
Selenium is framework built on top of a test engine such as JUnit or TestNG. On those engines, if you do nothing, the tool will interpret as a pass. In other words, in the absence of an assertion, the engines will assume the test passed. Since Selenium is built on top of this, the same can be said about Selenium. The code snippet below is a representation of what a Cucumber step looks like.
#When("my test step here")
public void myTestStep(...) {
boolean result = false;
try {
result = myTest(...);
}
} catch (Exception e) {
// log your exception (don't rethrow)
}
if (result) {
// log your passing test
} else {
// log your failing test
Assert.fail(); // This is what prevents subsequent steps to be executed. Remove it, and you should be able to continue to test.
}
For a JUnit or TestNG style method is basically the same. You may have an #AfterClass or #AfterTest hook that might handle telling the test framework to pass of fail test. TYPICALLY, passing assertions are implied (by not doing anything - i.e. executing an empty method). However, failing assertions are EXPLICIT and must be included somewhere. Just look for those Assert.fail() methods and remove them. A better alternative is to add a configurable property to your test suite that will turn this on or off.
} else {
// log your failing test
if (skip_off) {
Assert.fail(); // This is what prevents subsequent steps to be executed. Remove it, and you should be able to continue to test.
}
}
In this context, skip_off is the value of Boolean property you might have stored in a configuration file that when set to true, it will skip enforcing fail assertions.
package p111;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class Yahoo_c {
public static void main(String[] args) {
// TODO Auto-generated method stub
WebDriver wi = new FirefoxDriver();
wi.get("https://in.yahoo.com/?p=us");
wi.findElement(By.xpath("//[#id='UHSearchBox']")).sendKeys("pizza");
try {
Thread.sleep(50);
} catch (Exception e) {
System.out.println("wait ended");
}
String sl = wi.findElement(By.cssSelector("[id^='yui_3_12_0_1_14']")).getText();
System.out.println(sl);
}
}
Above is the code.
When i run this, execution goes until "pizza" being entered into yahoo search.Later with no error message in console execution terminates.
The error image is
Please help resolve this issue.Am trying to select pizza delivery from list.
You can try Name instead of path as the yahoo search has a name for selenium to work with. Please let know if Xpath is must for you to work then i will change my code.
public static void main(String [] arg){
WebDriver wi = new FirefoxDriver();
wi.get("https://in.yahoo.com/?p=us");
WebElement yahooSearch= wi.findElement(By.name("p"));
yahooSearch.sendKeys("pizza");
try {
Thread.sleep(50);
} catch (Exception e) {
System.out.println("wait ended");
}
String sl = wi.findElement(By.cssSelector("[id^='yui_3_12_0_1_14']")).getText();
System.out.println(sl);
}
}
Or you can use the same by ID
public static void main(String [] arg){
WebDriver wi = new FirefoxDriver();
wi.get("https://in.yahoo.com/?p=us");
WebElement yahooSearch= wi.findElement(By.id("UHSearchBox"));
yahooSearch.sendKeys("pizza");
try {
Thread.sleep(50);
} catch (Exception e) {
System.out.println("wait ended");
}
String sl = wi.findElement(By.cssSelector("[id^='yui_3_12_0_1_14']")).getText();
System.out.println(sl);
}
The option you are trying to click is a link in <a> anchor tag.. you can simply use By.linkText if you are specific on the link.
driver.findElement(By.linkText("pizza delivery")).click();
Problem is that you are sendKeys, even though the pizza is typed but the drop-down list does not appears because sendKeys is not equivalent of typing through keyboard. Work around is simple. You need to perform a keyboard action after writing "pizza".
// type pizza
wi.findElement(By.xpath("//[#id='UHSearchBox']")).sendKeys("pizza");
// now perform keyboard action (of pressing space key)
wi.findElement(By.xpath("String")).SendKeys(Keys.Space);
// now click on the pizza delivery link
wi.findElement(By.linkText("pizza delivery")).click();
Try above code in your project, after adding proper wait and with correct element locators.
Try this xpath //*[contains(text(),'pizza delivery')]
It'll work! :)
Check this in firepath and make sure you get only one node with the locator.
Someone could tell me how to write a functional application tests which combine Selenium Page Object Pattern and ExtentsReports (http://extentreports.relevantcodes.com/) to generate reports from these test cases. How to design test class? because I know that validation should be separated from page objects. What is the best approach to do this?
A sample piece of code would be very helpful
It is a good approach, of course, to separate your model (Page Objects) from you tests. For this to happen, you may use a layer of services, i.e. helper classes, which can interact both with business objects and page objects.
Note: I'm going to answer the second part of your question, not that on yet-another lib for reporting.
So, you have a business object:
public class Something {
boolean toHappen;
public Something(boolean toHappen) {
this.toHappen = toHappen;
}
public boolean isToHappen() {
return toHappen;
}
}
You also have your page:
public class ApplicationPage {
// how driver object is put here is your own business.
private static WebDriver driver;
#FindBy(id = "id")
private Button triggerButton;
public ApplicationPage() {
PageFactory.initElements(driver, this);
}
public static ApplicationPage open(){
driver.get("http://page.net");
return new ApplicationPage();
}
public void trigger() {
triggerButton.click();
}
}
So in order not to mix business objects and pages in tests, you create a service:
public class InevitableService {
public static void makeHappen() {
// just a very stupid code here to show interaction
Something smth = new Something(true);
ApplicationPage page = ApplicationPage.open();
if(smth.toHappen()){
page.trigger();
}
}
}
And finally your test
public class TestClass extends Assert {
#Test
public void test() {
InevitableService.makeHappen();
assertTrue(true);
}
}
As a result:
you have no driver in tests
you have no page objects in tests
you operate only high-level logic
Pros:
very flexible
Cons:
gets complicated over time
Considering your reporting tool - I believe it just listens the result of you tests and sends them to server. Or it just takes the xml/html results of you tests and makes pretty and useless pie-charts. Again, has nothing to do with POP.
Steps:
1. Declare variables under Test Suite class
public ExtentReports extent ;
public ExtentTest test;
2. Create object for Extent Managers User defined class
extent = ExtentManager.instance();
3. Pass extent parameter to the Page Object Class
inbound = new DemoPageObject(driver,extent);
4. Goto page object class method and Start with "Start log"
test = extent.startTest("View details", "Unable to view details");
5. For Success steps and we need end test
test.log(LogStatus.PASS, "The list of details are successfully displaying");
test.log(LogStatus.INFO, test.addScreenCapture(ExtentManager.CaptureScreen(driver, "./Send")));
log.info("The list of details are successfully displaying ");
extent.endTest(test);
6. For Failure and no need to end test
test.log(LogStatus.FAIL, "A Technical error is displaying under ");
7. Use #AfterMethod to handle error test cases
#AfterMethod
public void tearDown(ITestResult result) {
if (result.getStatus() == ITestResult.FAILURE) {
test.log(LogStatus.FAIL, "<pre>" + result.getThrowable().getMessage() + "</pre>");
extent.endTest(test);
}
}
8. Finally Adding results to the report
#AfterTest
public void when_I_Close_Browser() {
extent.flush();
}
public class ExtentManager {
public static ExtentReports instance() {
ExtentReports extent;
String Path = "./ExtentReport.html";
System.out.println(Path);
extent = new ExtentReports(Path, true);
//extent.config() .documentTitle("Automation Report").reportName("Regression");
extent
.addSystemInfo("Host Name", "Anshoo")
.addSystemInfo("Environment", "QA");
return extent;
}
public static String CaptureScreen(WebDriver driver, String ImagesPath) {
TakesScreenshot oScn = (TakesScreenshot) driver;
File oScnShot = oScn.getScreenshotAs(OutputType.FILE);
File oDest = new File(ImagesPath + ".jpg");
try {
FileUtils.copyFile(oScnShot, oDest);
} catch (IOException e) {
System.out.println(e.getMessage());
}
return ImagesPath + ".jpg";
}
}
I am trying to execute a data driven test using TestNG (& of course the dataprovider annotation).
My scenario is something like this ...
Use dataProvider to have a 2 dim array. (I am using this to read from Excel, but avoided it for brevity of the question).
#DataProvider(name = "featureTest")
public Object[][] dataSets() throws Exception {
return new Object[][] { {"TC_01", "testuser_1", "Test#123", "ABC Street", "123-456-7899" },
{ "TC_02", "testuser_1", "Test#123", "PQR Street", "222-456-7899" }
};
}
In the #Test method, there are several methods as per the functional flow -
#Test(dataProvider = "featureTest")
public void executeTest(String... data) throws Exception {
try{
feature_1.execute(data);
feature_2.execute(data);
feature_3.execute(data);
feature_4.execute(data);
}
catch(Exception e){
log.error("Error has occured");
}
}
Now my main problem is that the functional error can occur anywhere out of these 4 (n) methods that I specify in my #Test.
In case of an exception in any of the methods, I need to "Skip" the particular dataset and proceed to the next one.
For eg: In during execution of TC_01, an exception occured in feature_2.execute(), it should not execute the feature_3 and feature_4 methods.
Note:
I tried handling it using #BeforeMethod, #AfterMethod but still it goes through the unwanted methods that I want to avoid.
Thanks in advance for your help/inputs && apologies for the long question although a relatively simple concept to explain !!!
Its very simple. Use return!
Use a condition or try catch to evaluate the failure and then use a return statement;
One approach I can think of is the factory approach,
Your testclass
class Test{
Data data;
Test(Data){
this.data=data;
}
#Test
test1(){
feature_1.execute(data);
}
#Test
test2(dependsOnMethods ="test1"){
feature_2.execute(data);
}
#Test(dependsOnMethods ="test2")
test3(){
feature_3.execute(data);
}
#Test(dependsOnMethods ="test3")
test4(){
feature_4.execute(data);
}
}
And in your factory class
class Factory{
#Factory(DataProvider = "myDP")
public Object[] factoryTest(Data data){
new Test(data);
}
#DataProvider
public Object [][] myDP(){
enter code here
}
}
I'm trying to set up unit tests on a web crawler and am rather confused as to how I would test them. (I've only done unit testing once and it was on a calculator program.)
Here are two example methods from the program:
protected static void HttpURLConnection(String URL) throws IOException {
try {
URL pageURL = new URL(URL);
HttpURLConnection connection = (HttpURLConnection) pageURL
.openConnection();
stCode = connection.getResponseCode();
System.out.println("HTTP Status code: " + stCode);
// append to CVS string
CvsString.append(stCode);
CvsString.append("\n");
// retrieve URL
siteURL = connection.getURL();
System.out.println(siteURL + " = URL");
CvsString.append(siteURL);
CvsString.append(",");
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
and:
public static void HtmlParse(String line) throws IOException {
// create new string reader object
aReader = new StringReader(line);
// create HTML parser object
HTMLEditorKit.Parser parser = new ParserDelegator();
// parse A anchor tags whilst handling start tag
parser.parse(aReader, new HTMLEditorKit.ParserCallback() {
// method to handle start tags
public void handleStartTag(HTML.Tag t, MutableAttributeSet a,
int pos) {
// check if A tag
if (t == HTML.Tag.A) {
Object link = a.getAttribute(HTML.Attribute.HREF);
if (link != null) {
links.add(String.valueOf(link));
// cast to string and pass to methods to get title,
// status
String pageURL = link.toString();
try {
parsePage(pageURL); // Title - To print URL, HTML
// page title, and HTTP status
HttpURLConnection(pageURL); // Status
// pause for half a second between pages
Thread.sleep(500);
} catch (IOException e) {
e.printStackTrace();
} catch (BadLocationException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}, true);
aReader.close();
}
I've set up a test class in Eclipse and have outline test methods along these lines:
#Test
public void testHttpURLConnection() throws IOException {
classToTest.HttpURLConnection( ? );
assertEquals("Result", ? ? )
}
I don't really know where to go from here. I'm not even sure whether I should be testing live URLs or local files.
I found this question here: https://stackoverflow.com/questions/5555024/junit-testing-httpurlconnection
but I couldn't really follow it and I'm not sure it was solved anyway.
Any pointers appreciated.
There is no one conclusive answer to your question, what you test depends on what your code does and how deep you want to test it.
So if you have a parse method that takes an HTML and returns the string: "this is a parsed html" (obviously not very usefull, but just making a point), you'll test it like:
#Test
public void testHtmlParseSuccess() throws IOException {
assertEquals("this is a parsed html", classToTest.parse(html) ) //will return true, test will pass
}
#Test
public void testHtmlParseSuccess() throws IOException {
assertEquals("this is a wrong answer", classToTest.parse(html) ) //will return false, test will fail
}
There are a lot more methods besides assertEquals() so you should look here.
eventually it is up to you to decide what parts to test and how to test them.
Think about what effects your methods should have. In the first case the expected thing that should happen when HttpURLConnection(url) is called seems to be that the status code and url are appended to something called CvsString. You will have to implement something in CvsString so that you can inspect if that what you expected did actually happen.
However: Looking at your code I would suggest you consult a book about unit testing and how to refactor code so that it becomes well testable. In your code snippets I see a lot of reasons why unit testing your code is difficult if not impossible, e. g. overall use of static methods, methods with side effects, very little separation of concerns etc. Because of this it is impossible to answer your question fully in this context.
Don't get me wrong, this isn't meant in an offending way. It is well worth learning these things it will improve your coding abilities a lot.