I'm using Selenium to ease my testing burden and I have about 1,000 different drop down list combinations (spread across multiple pages and drop down lists) that need to be tested. Basically, what I would like to do is select each <option> inside of a <select>, click the Submit button, select an item (first, second, third, etc.) in the drop down list on the resulting page, click submit, and then go back and select the next item, in sequence. Each time, it should assert that a certain value (related to the drop down list value selected) is present on the final page. Does anybody know if this kind of logic is possible in Selenium?
I'm having a hard time explaining this, so hopefully this pseudo code clears things up
foreach option in select
select option
submit form
foreach option in select
select option
submit form
assert that page contains text that matches selected values
Edit: I have selected values from the drop down list while the recorder is playing, but it seems like the recorder isn't picking up the selected drop down list values. Nor have I been able to figure out how to perform the operation for each <option> in a <select>.
The first question I have is whether or not it's even possible. If it is, could somebody please point me in the right direction to get me started?
Edit 2: I'm not opposed to using another web automated testing utility. If anybody has any recommendations for a free alternative, please feel free to make that recommendation.
What language are using Selenium in? If you're just using Selenium by writing HTML, I'd recommend switching to a programming language and using Selenium RC -- bindings are available for a wide variety of languages, such as Java and Python. In Java, I believe the following would do what you want:
void test(Selenium browser, String startPageUrl,
String firstFormLocator, String firstSelectLocator,
String secondFormLocator, String secondSelectLocator) {
browser.open(startPageUrl);
for (String option : browser.getSelectOptions(firstSelectLocator)) {
browser.open(startPageUrl);
browser.select(firstSelectLocator, "label=" + option);
browser.submit(firstFormLocator); // Or click the submit button
for (String subOption : browser.getSelectOptions(secondSelectLocator) {
browser.open(startPageUrl);
browser.select(firstSelectLocator, "label=" + option);
browser.submit(firstFormLocator); // Or click the submit button
browser.select(secondSelectLocator, "label=" + subOption);
browser.submit(secondFormLocator); // Or click the submit button
// Do your assertions
}
}
}
The code isn't exactly readable, so it might be worth some time abstracting the page away slightly using the Page Object pattern. This also helps make the code more maintainable, for instance when you change the ID of an element, you only need to change it in the page object rather than every test.
Also bear in mind that doing this 1000 times isn't going to be quick. It might be worth seeing if you do similar testing just below the web interface to allow quicker feedback from tests, and then test the web interface is using the lower layer correctly. Also, do you really need 1000 tests? It seems that there's some redundancy in testing here -- is the 1000th test going to fail if the last 999 have passed?
Related
I'm using Selenium Basic to collect data from a website and store this into a database. The page I'm scraping is dynamic and loads more information as you scroll. I've been able to address most of this by using the implicit/ explicit waits, etc.
I am capturing all the IDs necessary to create the click action, which opens up another javascript popup for me to collect information there. However, even though I've been able to get these new IDs when the page loads by scrolling, when the app uses that new ID to click, I'm getting an error saying the element cannot be found. This is preventing me from opening up the javascript windows for these newly loaded rows.
When I go to collect this new data, the elements don't exist even though I was able to get the IDs for them.
When I look at the DOM in the browser and page source, all of it is there, so I don't believe it's an issue of letting the browser load.
I've tried utilizing the wait methods (implicit/explicit)...I've even put in hard 60 second waits through the routine. No matter what I do, the routine bombs out after the first 10 rows because it can't find the elements to the data it found after scrolling. I've also tried this using Chrome as well.
Unfortunately, the website needs to be private, so I can't provide the full code. The issue that's happening comes here:
driver.FindElementByXPath("//*[contains(text(),'" & DBA!ParseID & "')]").Click
The error I get is "Element not found for XPath("//*[contains(text(),'ID12345"')]
ParseID is the ID found from parsing elements within the body tag. So, I am able to collect all the IDs after loading all the data, but when it goes to click using the above code, it only works for the initial 10 rows. Everything loaded after that will not work (even though they've been loaded in the Browser for quite some time).
What I should be getting is, say 20 IDs which can create 20 clicks to javascript pop-ups to get more information. However, I am getting 20 IDs but the ability to only click on the first 10, even though I've loaded the entire page.
This issue hasn't been resolved the way I initially expected, but I've accomplished what I needed through a different and more efficient way.
First, when I researched this further by removing certain IDs in my loop, I noticed that this really didn't have much to do with data updating in the DOM or browser, but rather the ID itself not being found by a (still) unknown reason. It actually seems very arbitrary why it's bombing out. The ID matches the ID in the DOM, but when the string is being moved to the XPath, it can't find it in the DOM. I'm not sure why this would occur unless the string is breaking when being passed somehow, but I'll just let that one remain mysterious until someone smarter comes along!
What I did to accomplish what I needed is loop through the actual class N times, and pull the elements I needed within the classes. Rather than use the ID above as a unique identifier, I used the count of class web elements as the identifier. This worked with 90% less code.
Thank you all!
Let us say my test wants to see if a user can see an image on XYZ page. And let's say in normal usage, the user can only go to XYZ page by clicking a link on ABC page (might be the home page).
Now assuming the URL to XYZ page is not static, but maybe depends on the image, and can be generated in the code simply, I have two ways of writing the test:
Generate the URL in test and directly navigate to XYZ, and then check if the image is present.
Go to ABC like a normal user would, click on the link which takes you to XYZ and then check for image
For option 1, I feel like I get more test isolation. If the link on ABC page is not generated correctly or is broken for some other reason, this particular test should not fail, right? That should be the responsibility of some other test?
But for option 2, that is how a real user would do it. He would almost never try to guess the pattern of the URL and then navigate to it directly. And I cannot have a huge test that goes to every link and sees if it is not broken, that would be way too complicated. So this much sacrifice in test isolation is needed.
How should I decide between the two options? Is there a right way? Hopefully the question is not too subjective for stackoverflow.
It depends on what you're wanting to test. If you want to test the buttons or links themselves (ie: you're testing the whole user workflow), click on them just like the user would.
If, on the other hand, clicking these links is just a means to an end and that the real target of the test case is deeper into the app, I think it's perfectly fine to skip directly to the part of the app you're actually testing.
As an End User, best approach will be the Option 2 which also widen the coverage of your test hence you can check:
1. Whether links/ buttons are clickable and not throwing exception.
2. Click on above is navigating to correct page.
Option 1, can be used for test scenario where user doesn't bother about how to reach to the page rather focused only on the opened page contents.
Choosing any of these option is depending on your approach of test coverage and its scope.
I am looking for automated way to capture HTML after I do some actions on the web page.
For example I select some item in dropdown and HTML has been changed, i want to capture that HTML and dump into file. As result, I will end up with many different HTML files on my hdd.
I was thinking it might be possible to achieve that by using Selenium, maybe some other plugin which would give me possibility so save HTML in automatic manner to file.
do you mean source code?
for Python:
driver.page_source
for Java:
driver.getPageSource();
you can run these code after each step where page is changed
I think what you are asking to do will not be that easy. There are other questions on SO (e.g. this one) asking the same thing and there aren't really any good answers. I tried googling for a few mins to find a way to do this. I would think something more like a browser plug-in would exist that would do this for you.
If I were forced to code this using Selenium I would do something like the following...
Create a script that launches the browser and navigates to the page you want to track. In a user-defined interval, the script would grab the page source and compare it to the last capture. If the source is not the same, it would diff the two pages and write the diff to disk. I'm sure there are a number of diffing libraries you could find and use.
The problems with this approach...
If you made too many changes within the defined interval, you would get a glob of changes and not be able to differentiate what action made what change.
If you make the interval too small, you may run into perf issues.
Probably the most significant issue is going to be the fact that you run several tests and then go back and look at the diffs... but you won't have any way to tell what changes correspond to what action since you can't tie the two together other than order of occurrence.
What might be cool is if you could inject a button into the page that when clicked would popup an input dialog that you could type some text into and use that as a label for the upcoming action diff. For example, you click the button and type "choose price" - OK. Now you select a price from a dropdown. The next time you click the button, the script detects the button click and does a quick diff and writes it to disk using the "choose price" label... or something like that.
I found answer for my own question.
Start a selenium chrome driver server.
Use selenium client connect to and all changes could be captured by using code example below:
Code:
WebDriver driver = new RemoteWebDriver(new URL("http://127.0.0.1:9515"), DesiredCapabilities.chrome());
driver.get("http://google.com");
By by = new By.ByTagName("div");
List<WebElement> oldDivs = driver.findElements(by);
while(true){
try {
List<WebElement> newDivs = driver.findElements(by);
if (oldDivs != newDivs) {
for (WebElement element : newDivs) {
String a = element.getAttribute("a");
String b = element.getAttribute("b");
System.out.println(a + " :" + b);
}
}
}catch (Exception e){
System.err.println(e);
}
}
I start learning to write Cucumber test, and now I can write the test, but my test is too silly; I don't know I should focus what and ignore what. I always ask my co.op how to write a good test with Cucumber, and they give me some advices, but I feel not satisfy enough. So, please tell me about your opinion and give me some examples, thanks so much!
EDIT
I had an index page with a table, and 3 buttons(edit, detail, delete) in the last column each row of the table
and 1 button Create below the table, and the nav bar has a login form
So what thing I should check?
In my opinion, I think we shouldn't check login function and the content of the nav bar, because every page in this controller has the same layout
Maybe we should check total columns, total rows, the title, the icon css, the content of button, the css of whole page (border of table, width, height, font-family) ... Is this true?
I think you should prioritise the elements in your page, and check them.
As an example, when you test the login page:
Important elements of the login page
user name, password text boxes
login button
Not important elements (This all depends on your business requirement)
cancel button
other fancy text
etc..
and then in your Cucumber test, make sure you check the availability of user name, password text boxes and login button. The rest of the elements you can ignore. Otherwise you will be spending unnecessary time on testing non-important things.
Again, the priorities of your given page is depending on the business requirements of your project.
Options for a dropdown on a webpage I am testing are dependent upon the values supplied for earlier textboxes and selects (E.g. based on the currency and amount specified, dropdown for product will show appropriate values. With no values, the supplied the dropdown is blank.).
Now, although I have provided the values for currency and amount, the product dropdown is still blank. It is not fetching the filtered values based on earlier data supplied. I am using Selenium server (2.24.1) and writing scripts in Java in Eclipse with TestNG and testing on IE8.
When inspected, the dropdown is no different from others, only its options change based on the values of other elements on the page. The web application is developed in Java (Wicket framework).
The Selenium code:
selenium.select(ownerBranch, "label=4521 - Branch one");
selenium.select(currency, "label=SEK - Swedish kronor");
Thread.sleep(sleep);
selenium.type(amountSantioned,"100000");
Thread.sleep(sleep);
selenium.click(chooseLoanTermBymatDate);
Thread.sleep(sleep);
timeNow=Calendar.getInstance();
timeNow.add(Calendar.DATE,+360);selenium.type(maturityDate,dateformat.format(timeNow.getTime()));
Thread.sleep(sleep);
selenium.type(amountSantioned,"100000");
Thread.sleep(sleep);
selenium.select(serviceDelChannel, "label=BackOffice");
Thread.sleep(sleep);
selenium.select(product, "label=");
Thread.sleep(sleep*2);
selenium.select(product,"label=LN7292 - Consumer loan for Year2026");
Thread.sleep(sleep);
I'm not going to try to reproduce the issue (if you can point me to a publicly visible site with similar behaviour, I might test it), so I'm only taking a guess here:
Since Selenium RC is written in pure Javascript and "only" firing change events on selecting values from drop-downs, Wicket is probably waiting for something else or relying on a completely different mechanism.
Things you can try:
Use Selenium WebDriver. Selenium RC has been deprecated for over a year now, because it had serious technical limitations (you might have just bumped into one) that are now solved by WebDriver. Also, you won't ever have to use Thread.sleep() again (although I'm almost sure it could be got rid of even here, mostly). This solution is the most painful, but is almost guaranteed to work well, because WebDriver behaves like a real user.
Call selenium.fireEvent() on all the input elements you're interacting with. Useful events might be focus, blur, maybe even click in between them.
Calling selenium.keyPressNative(String.valueOf(KeyEvent.VK_ENTER)) (presses Enter natively) after you every change of a dropdown. If the changed dropdown is not focused before this, you might need to focus() it beforehand.
The painful way that tries to simulate user's behaviour as close as possible instead of using JS methods: Instead of using select(), try to focus() a dropdown element, then select one of its options by pressing Down arrow repeatedly, then Enter.