How to perform feasible web smoke test with Selenium WebDriver? - selenium

I have been doing some research on feasible and faster web page loading test with Selenium. A general idea of smoke testing is to click and navigate through the whole site to make sure the pages load properly. I was initially thinking to use some kind of ways to capture the http status code through some kind of http libraries since Selenium does not have any native support for that. But, I found it is not what I want since it will simply return Each and Every links of the site and most of them will be the ones I do not want. So the best way will be to perform actual click and take pages in return. The problem there is the execution time it will take. However, that’s what I am doing currently. Splitting the whole application into different modules and click through all VISIBLE links and take page objects in return with known selector. I am using FindElements() method to grab all the links of a page and click back and forth to test page load. I am doing something like the following:
Is there a better way to improve the performance?
WebElement deliveredChartDailyFocus = driver.findElement(By.id("delivered-chart-daily"));
deliveredChartDailyFocus.click();
// Get a list of all the <rect> elements under the #delivered-chart-daily element
List<WebElement> children = deliveredChartDailyFocus.findElements(By.tagName("rect"));
WebElement elementToClick = null; // variable for the element we want to click on
for (WebElement we : children) // loop through all our <rect> elements
{
if (we.isDisplayed())
{
elementToClick = we; // save the <rect> element to our variable
break; // stop iterating
}
}
if (elementToClick != null) // check we have a visible <rect> element
{
elementToClick.click();
}
else
{
// Handle case if no displayed rect elements were found
}

I would never call process of verification of every single link 'smoke testing'. For example how ISTQB defines this "A subset of all defined/planned test cases that cover the main functionality of a component or system, to ascertaining that the most crucial functions of a program work, but not bothering with finer details". And ths actually mean to exacute some meaningful scenarios and check some small flow/piece of functionality. Only clicking every link will check correctness of links but not computations or logic performed by server side. As for improving speed of passing tests you can consider running tests in parallel.

Related

Salesforce's iframes

In order to support new lightning of salesforce, I'm trying to rewrite existing e2e tests. We have an integrated app, which opens in inframe in both cases (classic design and new lighting). In the case of old site design, we have to dig into the second level of nesting
<iframe ...>
...
<iframe id='my app'>
In the case of the newest design, yet another one level of nesting was added (my iframe is also in the deep).
I'm facing the problem, that I'm not able to switch to the second iframe. I always get "The iframe in which the test is currently operating does not exist anymore." Even if I want to await the simplest Selector with "div" element for example.
await t.expect(Selector('div').find('iframe').exists).eql(true);
await t.switchToIframe(Selector('div').find('iframe'));
const nextIframe = Selector('div');
const dom = await nextIframe(); <--- here it throws
I've checked the the first one selector, it returns exactly what I want.
What can cause my problem?

Selenium tests fail with azure pipeline sometimes and pass locally

Test cases fail while not finding a link or any validation messages after a button click.
I used explicit waits for page to load:
var waitForDocumentReady = new WebDriverWait(WebDriver, TimeSpan.FromSeconds(10));
waitForDocumentReady.Until((wdriver) => (WebDriver as IJavaScriptExecutor).ExecuteScript("return document.readyState").Equals("complete"));
For wait specific div of validation messages:
WebDriverWait wait = new WebDriverWait(WebDriver, TimeSpan.FromSeconds(10));
wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.ClassName("validationErrors")));
But test cases pass sometimes with pipeline and fails sometimes.
I would recommend following:
When ever your tests fail take a snapshot at that moment.
sometimes when you run your tests locally the network communication
is a bit faster than running on server. Which means a spinner or a
loading control may not appear locally because results were retrieved
fast enough but the loader will appear when there is delay from
server in sending the response to client.
If you are trying to run your tests in FF headless on remote grid
setup then it is not yet stable in my experience.
Identify the pattern in failed scenarios which frequently fail and
try and run them multiple times in a loop and identify the pattern of
failure. In one of my case there was an actual bug in the performance
of the application which used to get reproduced whenever the tests
ran immediately in bulk
I was having this issue, except my test would always fail in Azure Pipelines but pass locally. Not running in "headless" mode fixed my problem. To do this, make sure "Test mix contains UI tests" is checked in your "Visual Studio Test" task.
There are a couple of things you need to take care as follows:
Test cases fail while not finding a link or any validation messages after a button click: A lot depends on the attributes of the button. In case the button contains either of the following attributes/events the DOM Tree would be getting updated and subsequently trying to find the desired element may fail:
onclick() event:
<button onclick="myFunction()">Click me</button>
jQuery click() Event:
$("p").click(function(){
alert("The paragraph was clicked.");
});
So after a button click, to find the desired element you need to induce you have to induce WebDriverWait for the ElementExists().
You can find a relevant discussion in ExpectedConditions.ElementIsVisible returns TimeoutException even when element is present
ExecuteScript("return document.readyState").Equals("complete"): This line of code is not that effective to ensure if the desired element(s) are present/visible/interactable with in the HTML DOM.
You can find a relevant discussion in Do we have any generic function to check if page has completely loaded in Selenium
However to wait for specific div with ElementExists() should have worked. The relevant HTML would have helped us to analyze what went wrong. However, if the validationErrors related element is based on HTML5 Constraint validation then you have to use the GetAttribute() method.
You can find a relevant discussion in How to handle html5 constraint validation pop-up using Selenium?

how to override findElements() implementation in selenium with moveTo() each element using java?

I am using selenium webDriver with Java and looking for a solution to find elements by moving to each element in the List at the time of selenium locating it. A solution I am looking for specific to 'ChromeDriver', as chrome driver works with point/coordinates, each time my script failed to execute drag and drop list of elements identified from one location to another.
Scenario description: My application is having two tables (T1 and T2) with the list of 'li and ui' as subitems under each table row. I need to drag and drop 'T2' row/rows 'web elements' to matching web element under 'T1' row(same may be visible or not visible in the viewport during drag and drop- But I have used moveTo() method).
Issue: When I am executing the scripts in Chrome, web elements not present in the current viewport of 'T2' are clicked and dragged to matching 'parent web element' in 'T1'. But after the first run, web page alignment breaks and subsequent drag and drops are failing due to 'previously' identified elements position changed.
I have tried multiple approaches like, click the 'T2 element 1 and move and perform drag and drop, Using javascript executor display the element in viewport etc.. but each time the UI alignment breaks.
I would like to know that if anyone has worked on the custom implementation of 'Selenium FindElements() method with a MoveTo() function'?
something like:
#Override
public List<WebElement> findElements(By arg0) {
List<WebElement> moveAndFind = null;
try{
WebElement firstIndex = Driver.findElement();//Move to first matching element of By argument.
moveAndFind.add(firstIndex); // Collect all the matching elements in the web page by capturing the updated location - specific to Chrome driver
}catch(WebDriverException ex){
ex.printStackTrace();
}
return moveAndFind;
}
To answer specifically to your question, you cannot override the implementation of FindElement (or, since I'm not that familiar with the Java implementation, I'm not aware of something).
Now, to overcome your issue, you have several options:
Since you already have your list created, you could always move from the end of the list. This way, the order of elements is always the same with the initial index.
Use lambda expressions to identify the elements in your list by anything else but index.
Refresh and reconstruct your list after every move of an element. Depending you how many elements you need to move, this may prove to be the worse option performance wise.

How do you select elements in selenium that have a period in their id?

I am trying to write code that will select all options for an HTML drop-down menu. I have written the following code which I believe should work.
public void testSelectMultipleOptions () {
// code to get to report page
selectAllOptions("param.Status");
// code to run report and switch to the result page
}
public void selectAllOptions(String htmlID) {
List<WebElement> options = selenium.findElements(By.cssSelector("select#"+htmlID+" > option"));
for(WebElement option: options) {
option.click();
}
}
When I run this code no options are selected in the drop-down. I believe the problem I am having is caused by the fact that I have an HTML element with a period in the id but I do not have the ability to change the underling HTML code for the page.
There is incredibly bad development practice. I know you don't have the ability to change it, but if you can, point out that it's very very bad. Why? Two reasons.
In CSS, the rules based on classes generally start with a period.
In CSS selector frameworks, including jQuery/Sizzle and what Selenium is doing in this example, the period has a special meaning - mainly to select elements based on many rules. This is why it's tripping here here - you can see the same thing if you run the CSS selector direct into Chrome or Firebug - it will fall over as well.
Using a period in the ID for your elements is going against all this. Annoyingly the HTML spec allows for this.
Anyway, all is not lost, there are many ways around it.
First, you can escape it:
select#param\\.Status
Second, you could use a slightly more elaborate selector:
select[id='param.Status']
Finally, you could use XPath:
//select[#id='param.Status']

How to get WatiN to scan dynamically loaded content?

The situation is that I have a page that uses some AJAX calls to retrieve content from the server, then puts those results into a chunk of html generated by another script. The problem is, I can't select with watin any of the elements of this new piece of html. It can be viewed in the browser, and comes up when I hit F12 and scan through the code, but still WatiN can't see it.
Is this because WatiN only scans through the html source of the page, and not the current version of the HTML? I think a similar situation would be:
html -
<script type="text/javascript">
$('#foo').html("gak");
</script>
...
<div id="foo">bar</div>
then when I try and assert -
Assert.IsTrue(browser.Div("foo")).ContainsText("gak"));
it will return false.
Any ideas on this? or is my best option to just write a bunch of jQuery, and browser.Eval() it?
I test AJAX pages quite a bit. The key is to wait until the asnyc postback has completed. If you have
Assert.IsFalse(browser.Div("foo")).ContainsText("gak");
browser_action_that_changes_bar_to_gak
>> Here you need to wait <<
Assert.IsTrue(browser.Div("foo")).ContainsText("gak");
In the "wait" section you can do a System.Threading.Thread.Sleep(numberOfMilliseconds) <- this is not the best way, but it is really simple. Once you determine that waiting is what you need to do, a better way to wait is to poll the status rather than way numberOfMilliseconds each time. I believe different AJAX libraries do things differently, but what works for me is really similar to this: http://pushpontech.blogspot.com/2008/04/ajax-issues-with-watin.html
I put the JavaScript into an Eval() in a helper function in the my base Page class rather than having to inject it into every page like the article did.
.
my Base Page class contains:
public bool IsInAsyncPostBack()
{
const string isAsyncPostBackScript = "Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack()";
return bool.Parse(this.Document.Eval(isAsyncPostBackScript));
}
And then my WaitForAsyncPostback is basically the same as in the linked post, but I added a max wait time. Before going to Page classes (awesome; do it!) I made these static functions somewhere else and it worked too.
This is almost surely a timing issue. The jQuery has not updated when you test. Rather than introducing any artificial pause or wait it's best to wait for something to show that your AJAX has worked as expected.
In this case a WaitUntil should do the job nicely:
Assert.IsTrue(browser.Div("foo")).WaitUntil(c => c.Text.Contains("gak")));
This works for most updates and the like. Another common waiting pattern is on data loading say, where you'd have a spinning wheel displayed. Then you could wait until this wheel is gone with a something like:
WaitUntil(c => c.Style.Display == "none");