In a recent AngularJS-based job interview, the client discussed the need for Web UI regression testing.
The client briefly presented a scenario where they had rolled out a last minute DOM change to production, but it turns out that the new button they added was causing some issues on the page (I believe the exact issue was that the new button was getting hidden, but no one caught the issue ahead of time).
The main thing that came out of the conversation was that it would be great if I could come up with a Web UI regression test that compares old UI with new UI.
Not being a regression testing expert myself, I seek some advice regarding the best UI testing tools.
Having some AngularJS experience, my first approach would be to use Protractor - which I know is based on Selenium WebDriver.
I've also come across some Visual UI regression tools such as https://github.com/garris/BackstopJS, http://screenster.io/ , and https://www.parasoft.com/capability/web-ui-testing/ .
So my main question here is for the AngularJS testing folks: What would be the best solution to test for DOM changes in an application ?
I apologize ahead of time if this question is too vague, but I am seeking advice on the best approach for UI Regression Testing.
thank you in advance...
Bob
I took sometime to answer this one as I feel this is important and your client's scenario is pretty much valid and happens in real time. I hope this would clear out some concepts regarding web UI testing & automation.
I am assuming that you are aware that why and how the DOM changes.It is mostly due to changes in javascript functions or ajax calls which happen rapidly that our test scripts trying to locate Web Elements might not catch them in that specific time window leading to the famous Stale Element Exceptions. Now let us focus on how this happens in the background -
As you can see the DOM structure above, everytime a webdriver instance/session is created a reference of the web elements is stored which is in turn stored as JSON ref and passed to selenium webdriver and Protractor which is built on top of it.This drives the browser as we see in browser testing and automation.
When a browser refreshes, navigates or reloads, the DOM tree gets destroyed and recreated again, hence every reference to this DOM element become invalid. Element references could be lost or broken in that specific time frame and thus we get the stale element exceptions.
To be honest avoiding these scenarios is not possible and the worst part is it might not happen as often, So how do we tackle this annoying scenario? There are quiet a few work arounds to catch them efficiently-
To recreate entire reference hierarchy in catch block and call the same method recursively until maximum tries or unbound until some another exception.
To reference the element locators as a String rather than referencing them using the WebElement because Strings do not go stale.
Both of the above methods are discussed in detail in the following links please go through them as I do not want put code in this post just to keep it simple for understanding concepts.
http://darrellgrainger.blogspot.in/2012/06/staleelementexception.html
http://www.assertselenium.com/java/what-is-staleelementexception-in-webdriver/
http://softtechlabs.com/2015/09/deal-with-staleelementreferenceexception/
I hope this clears out many things for you!
I would vote for use of protractor. You can have test cases that include testing of control states so in the example you mentioned if you have a test that verified when the button was supposed to be enabled and another when disabled (or displayed/not displayed), it would have failed.
Related
I have seen many articles regarding the changes in Angular2 . But I can't find much advantage in using Angular2. Can some one point out some new things that can be done using Angular2 which can't be done using the previous versions.
I know there are changes like $scope changed to this. I'm not asking for changes. I'm asking for new features that is in Angular2.
The TL;DR Version
Because ES6 is important to pick up, so no need for a custom dependency management system anymore. ES6 and Angular 1 together get ugly fast, as they together introduce a bajillion coding styles :(
Although the library is overall heavier, the architecture it uses (all component based) is a lot faster, lighter, and modular for a scalable application. See http://info.meteor.com/blog/comparing-performance-of-blaze-react-angular-meteor-and-angular-2-with-meteor
You receive (upcoming) Server Side Rendering, which enables fast initial load time and Search Engine Optimization (Yay!) See: https://github.com/angular/universal
You receive WebWorker friendliness, which makes your application able to "multi-task". See: https://github.com/angular/angular/blob/master/modules/angular2/docs/web_workers/web_workers.md
Shadow DOM is not fully inherited by Angular 2 yet, but I'm sure it will be. It has some support right now.
The whole concept of $scope is gone. You receive two way data binding with anything you put in your ES6/TypeScript class, but anything more you need to create a Observable or promise. Unfortunately, you can't just shove anything into the scope, digest, and WALAH! anymore.
And of course, all the cool stuff they mention on their website: https://angular.io/features.html
Hope that helps!
Support for different languages TypeScript, Dart, ES5, ES6.
Change detection is much more effective
Support for isomorphic applications where the same code can run on the server, the browser and a WebWorker in the browser
Moves more work to build time to reduce the time for the initial page load.
Simplified binding syntax
Improved DI
There are also lots of mostly smaller and tiny features that Angular2 doesn't (yet?) support which Angular 1.x does.
The application under test is built on angular because of which the xpaths are failing to locate the element . I am using selenium web diver for automating the tests and google chrome browser.
Can anybody kindly specify how to break down angularjs components to basic html elements while creating the xpath or any other way i can adapt to find the exact element on the page.
Any link or path or tips to follow.
I have searched a lot but no luck till now.
Starting with covering some general concerns.
When testing AngularJS applications, the timing issues are usually the most common - this is partially why we have tools like Protractor built mainly to test AngularJS applications. What makes it unique is that it works in sync with Angular, knowing when it is ready to be interacted with. It also provide AngularJS specific locators which makes locating elements much easier, samples:
element.all(by.repeater("item in items"));
element(by.binding("mybinding"));
element(by.model("mymodel"));
If you can, you should consider switching to Protractor - the test flow is natural - almost no explicit waits, a lot of convenient syntactic sugar and much more element-locating options.
If not, you can still use Angular-specific attributes to locate elements, examples:
driver.findElements(By.xpath("//*[#ng-repeat='item in items']"));
driver.findElement(By.xpath("//*[#ng-binding='mybinding']"));
driver.findElement(By.xpath("//*[#ng-model='mymodel']"));
Though, as usual, you should prefer to use ids, classes and other "data-oriented" attributes.
Things can easily go wrong with the above sample expressions - imagine web developers add a "tracking" to the repeater, or rename the ng-repeater to data-ng-repeater.
As a side note, using Angular specific things like ng-* attributes in your tests, would make the test codebase tight to this specific technology used to build the application under test. It is not necessarily a bad thing but you should keep it in mind.
I am an AngularJS newbie. I have an AngularJS app that causes the browser to report 'Page has become unresponsive'. What are the steps I should take to debug and find what is causing this behavior?
(I am asking this way, rather than posting code and having someone solve my problem, so I can learn how to solve similar problems for myself in the future)
you can check few things if page goes unresponsive
check the page watch count or here (I prefer implementation in link 2)
once you know the watch count, try reduce the watch count if its too much
can you use one-time binding (hence reducing the watchers) read here
if you have ng-repeat and need two way binding & use track by
Based on the information you provided, I think that the error isn't related to AngularJs itself. You might see some information on this site, which describes clearly how to solve this issue.
What are the steps I should take to debug and find what is causing this behavior?
Typically, the most common way to debug AngularJs application is to use Chrome Dev tools, inspect element. It allows you to put any breakpoints in order to verify your application.
Alternatively, if you are using Chrome, you could use AngularJS Batarang which is very great chrome extension to debug your AngularJs app.
Usually AngularJS causes the browser to be unresponsive when there are too many watches.
There is a Chrome extension AngularJS Batarang that allows the inspection of each binded expression.
You can view the time required for each expression to load (both in ms and as a percentage of total application load).
Take a look at these articles:
Removing the Unneeded Watches
Debugging performance problems in AngularJS with Batarang and Chrome DevTools
And at this module BindOnce.
Silverlight had a nice feature ("design time data") that allowed one to indicate data for use in views which was only used at design time. This allowed a designer to work with fleshed out screens that looked realistic rather than just a skeleton.
(for a bit of background on this feature in Silverlight, here's a random msdn post about it)
Is there a similar approach for doing this in angularjs?
I don't think that's possible w/ Angular. Angular populates the views as it's processed, so you see the "skeleton" until it's done processing. The design data you talk about would still have to be processed by Angular to be viewable.
You could always populate your scope with "design" data if you are waiting for API's to be built out, etc. You could then work with the view html/css in Chrome dev tools or with any other browser tool set. Not sure that's what you're looking for as it's still technically "runtime" development, but it might get you closer to what you are looking for.
I am working on my first DotNetNuke website and there is a requirement for all the custom module functionality I am developing to be available with JavaScript disabled.
However, when I create a module that contains a simple submit button, i.e.<input type="submit" />, DotNetNuke displays a critical error with JavaScript turned off but works as expected with JavaScript turned on.
When I attach to the running process using Visual Studio, the unhandled exception is thrown from admin/Skins/Nav.ascx.vb line 177. The inner exception message is "Invalid JSON primitive: ."
My research online only managed to turn up this forum post (Postbacks are not working when Javascript is disabled in the browser) that appears to be the same problem as mine, but no solution is provided.
Can anyone shed any light on this issue? Is it viable to be attempting to write non-JavaScript functionality in this version of DotNetNuke?
Update: it turns out that another website designed recently with Dot Net Nuke by the company I am working for is having the same problem with non-javascript postbacks when using DNN version 5.1.4 but it does not have the problem (i.e. it can postback without javascript) in DNN version 5.0.1.
So perhaps a hard dependency on javascript has been introduced at some point after version 5.0.1. We are investigating this possibility further and I will keep this question updated as we go. Obviously I still welcome anyone's input on the subject.
Update: i've started a thread on the Dot Net Nuke forums to see if I can get any help there. If any solutions come up I'll post them here. Trying to find official DNN stance on support for javascript disabled functionality
One of the developers in the office found a workaround to get postbacks working with javascript disabled. Unfortunately since he does not have a Stack Overflow account, I will try to translate his solution as best I can for those who are interested. Bottom line is postbacks with Javascript disabled is possible once you make a few changes to the Dot Net Nuke environment.
Step 1 - Change the menu module. In our case we used the Telerik RadMenu.
<dnn:NAV runat="server" id="dnnNAV" ProviderName="DNNMenuNavigationProvider" IndicateChildren="false" ControlOrientation="Horizontal" CSSControl="mainMenu" />
becomes
<dnn:RADMENU runat="server" id="dnnRADMENU" MaxLevel="2" EnablePageIcons="False" PagesToExclude="" ShowPath="True" />
Step 2 - Remove the actions and visibility modules.
<dnn:ACTIONS runat="server" id="dnnACTIONS" ProviderName="DNNMenuNavigationProvider" ExpandDepth="1" PopulateNodesFromClient="True" />
<dnn:VISIBILITY runat="server" id="dnnVISIBILITY" minicon="images/DNN-minus.gif" maxicon="images/DNN-plus.gif" />
Step 3 - Download the DNN source and make two changes in the LibraryUI\Utilities\ClientAPI.vb file.
Line 155:
DotNetNuke.UI.Utilities.ClientAPI.RegisterClientReference(objButton.Page, DotNetNuke.UI.Utilities.ClientAPI.ClientNamespaceReferences.dnn_dom)
becomes
If Not objButton.Page.IsPostBack Then
DotNetNuke.UI.Utilities.ClientAPI.RegisterClientReference(objButton.Page, DotNetNuke.UI.Utilities.ClientAPI.ClientNamespaceReferences.dnn_dom)
End If
Line 355:
ClientAPI.GetCallbackEventReference(objPage, "", "", "", "")
becomes
If Not objPage.IsPostBack Then
ClientAPI.GetCallbackEventReference(objPage, "", "", "", "")
End If
Step 4 - compile the Dot Net Nuke library.
Note: Also make sure you are not logged in as an admin or host, as the admin/host panel at the top of the page will also break if you attempt to postback with javascript disabled.
Hope this helps someone else. If you feel like I'm missing some important details, let me know and I'll try and fill in what's needed.
DotNetNuke relies heavily on JavaScript and I doubt there is a real easy way around it - at least considering you need to support all functionality. Perhaps you can clarify that?
The the bottom line here is that you're going to need to modify DotNetNuke to meet your needs. It certainly isn't impossible to get it working, but I would venture a guess that it just plain isn't worth it for most people.
If, as you said, you need to retain ALL functionality without using JavaScript, you're going to have a pretty substantial amount of work to do.
I'd suggest, to get started, you download the source package, set up a development environment on your local machine, turn off JavaScript in your browser and start taking notes. This will help to determine the level of effort involved.
I'm guessing you won't get a lot of responses out of this one (as the poster in the forum thread you linked to didn't) as very few people have sat down in front of DotNetNuke with this as a requirement.
Also, keep in mind that any time you're making substantial changes to the DotNetNuke framework, you're interfering with your ability to easily perform upgrades in the future. Just another thing to think about.
I believe that I've seen the leadership in DNN say that they've taken a hard dependency on JavaScript, and have no intention at this time of considering a non-JavaScript compatible scenario.
That being said, being able to do a simple postback shouldn't be too difficult to support. I would look around in the Client API area for the error that you're describing. A lot of the Client API code is in the DotNetNuke.WebUtility assembly, which is a separate download from CodePlex to get the source.