I've had a lot of trouble trying to come up with the best way to properly follow TDD principles while developing UI in JavaScript. What's the best way to go about this?
Is it best to separate the visual from the functional? Do you develop the visual elements first, and then write tests and then code for functionality?
I've done some TDD with Javascript in the past, and what I had to do was make the distinction between Unit and Integration tests. Selenium will test your overall site, with the output from the server, its post backs, ajax calls, all of that. But for unit testing, none of that is important.
What you want is just the UI you are going to be interacting with, and your script. The tool you'll use for this is basically JsUnit, which takes an HTML document, with some Javascript functions on the page and executes them in the context of the page. So what you'll be doing is including the Stubbed out HTML on the page with your functions. From there,you can test the interaction of your script with the UI components in the isolated unit of the mocked HTML, your script, and your tests.
That may be a bit confusing so lets see if we can do a little test. Lets to some TDD to assume that after a component is loaded, a list of elements is colored based on the content of the LI.
tests.html
<html>
<head>
<script src="jsunit.js"></script>
<script src="mootools.js"></script>
<script src="yourcontrol.js"></script>
</head>
<body>
<ul id="mockList">
<li>red</li>
<li>green</li>
</ul>
</body>
<script>
function testListColor() {
assertNotEqual( $$("#mockList li")[0].getStyle("background-color", "red") );
var colorInst = new ColorCtrl( "mockList" );
assertEqual( $$("#mockList li")[0].getStyle("background-color", "red") );
}
</script>
</html>
Obviously TDD is a multi-step process, so for our control, we'll need multiple examples.
yourcontrol.js (step1)
function ColorCtrl( id ) {
/* Fail! */
}
yourcontrol.js (step2)
function ColorCtrl( id ) {
$$("#mockList li").forEach(function(item, index) {
item.setStyle("backgrond-color", item.getText());
});
/* Success! */
}
You can probably see the pain point here, you have to keep your mock HTML here on the page in sync with the structure of what your server controls will be. But it does get you a nice system for TDD'ing with JavaScript.
I've never successfully TDDed UI code. The closest we came was indeed to separate UI code as much as possible from the application logic. This is one reason why the model-view-controller pattern is useful - the model and controller can be TDDed without much trouble and without getting too complicated.
In my experience, the view was always left for our user-acceptance tests (we wrote web applications and our UATs used Java's HttpUnit). However, at this level it's really an integration test, without the test-in-isolation property we desire with TDD. Due to this setup, we had to write our controller/model tests/code first, then the UI and corresponding UAT. However, in the Swing GUI code I've been writing lately, I've been writing the GUI code first with stubs to explore my design of the front end, before adding to the controller/model/API. YMMV here though.
So to reiterate, the only advice I can give is what you already seem to suspect - separate your UI code from your logic as much as possible and TDD them.
See also: JavaScript unit test tools for TDD
I've found the MVP architecture to be very suitable for writing testable UIs. Your Presenter and Model classes can simply be 100% unit tested. You only have to worry about the View (which should be a dumb, thin layer only that fires events to the Presenter) for UI testing (with Selenium etc.)
Note that in the I'm talking about using MVP entirely in the UI context, without necessarily crossing to the server-side. Your UI can have its own Presenter and Model that lives entirely on the client-side. The Presenter drives the UI interaction/validation etc. logic while the Model keeps state information and provides a portal to the backend (where you can have a separate Model).
You should also take a look at the Presenter First TDD technique.
This is the primary reason I switched to the Google Web Toolkit ... I develop and test in Java and have a reasonable expectation that the compiled JavaScript will function properly on a variety of browsers. Since TDD is primarily a unit testing function, most of the project can be developed and tested before compilation and deployment.
Integration and Functional test suites verify that the resulting code is functioning as expected after it's deployed to a test server.
I'm just about to start doing Javascript TDD on a new project I am working on. My current plan is to use qunit to do the unit testing. While developing the tests can be run by simply refreshing the test page in a browser.
For continuous integration (and ensuring the tests run in all browsers), I will use Selenium to automatically load the test harness in each browser, and read the result. These tests will be run on every checkin to source control.
I am also going to use JSCoverage to get code coverage analysis of the tests. This will also be automated with Selenium.
I'm currently in the middle of setting this up. I'll update this answer with more exact details once I have the setup hammered out.
Testing tools:
qunit
JSCoverage
Selenium
What I do is to poke the Dom to see if I'm getting what I expect. A great side effect of this is that in making your tests fast, you also make your app fast.
I just released an open source toolkit which will help with JavaScript tdd immensely. It is a composition of many open source tools which gives you a working requirejs backbone app out of the box.
It provides single commands to run: dev web server, jasmine single browser test runner, jasmine js-test-driver multi browser test runner, and concatenization/minification for JavaScript and CSS. It also outputs an unminified version of your app for production debugging, precompiles your handlebar templates, and supports internationalization.
No setup is required. It just works.
http://github.com/davidjnelson/agilejs
Related
My TLDR; version of my question is "Is there a way I can integrate with qunit such that Dalek can get the correct context when it needs it, or conversely, can I get Dalek to run setup/teardown asset-pipeline-compiled Ember javascript to build a context for it to run tests on?"
Firstup Dalek look awesome! All my tests are currently written in qunit. I'm having some problems automating tests around a component I'm building in Ember. The component is a kind of WYSIWYG textarea.
(BTW, my qunit tests are being driven from a route within a rails application.)
To automate testing, my qunit scripts have a setup and tearDown that create a pristine textarea each time. Each test creates some content in the textarea, then interacts with it somehow doing some assertions on it.
That's all well and good, except that I require much better browser simulation than qunit can provide me with (and I'm really running out of patience for writing my own range-related browser-response simulation code).
The things I need to do mostly are:
1. Move the caret around using arrow keys, and type characters.
2. Click at specific points in the textarea (not x,y co-ords, but rather a specific points in the text).
It struck me that Dalek could totally help with this, but the way I'm doing this workflow, I think I'd either need Dalek to be remote controllable via my qunit tests, or else somehow rewrite my tests in Dalek, but to do that, I'd need to be able to get Dalek to use jQuery and Ember to create the component and data context for the setup/teardown, which I'm not even sure Dalek supports.
What I really need is part-integration, part-unit testing, and there doesn't seem to be a great answer in the JS/Rails/Ember testing space that will handle this set of conditions.
I fear DalekJS is not the tool you need right now, even if it is "my little tool" I suggest to use Karma (former called Testacular) - which was originally developed to test AngularJS applications: http://karma-runner.github.io/0.12/index.html
You could use it together with Protractor https://github.com/angular/protractor
It depends on selenium, but is fairly easy (compared to some other tools) to set up.
There is also a manual on how to use it in combination with Ember: http://karma-runner.github.io/0.10/plus/emberjs.html
I have a Yii project that is starting to rely more heavily on javascript for a lot of its operation.
To achieve a decent level of test coverage I'd like to use QUnit to test the javascript. Much of the javascript relies on ajax calls to pick up data from models (e.g. lists of items in drop downs).
I'd like to be able to use my Yii fixtures to set the database to a known state before running the QUnit tests - does anyone know of a way to make this happen? Or can anyone suggest another javascript unit testing framework that works well with Yii?
I would take a look at Venus (www.venusjs.org). It works with QUnit (and other test libraries) and may give you something close to what you are looking for. If you have questions, I'd be happy to work with you. Disclaimer: I am the creator of Venus.
I would like to test a web app that was drastically redesigned to use ExtJS to drive its UI.
I have done some online searching but couldn't find any recommendation for a good framework to handle it properly.
Up till now we have been using WatiN to create tests.
Note that we do not own the web app code.
What are the best options currently available?
You should look at using Siesta, it's a unit testing and functional testing tool designed to help you test Ext JS and Sencha Touch (and it's also used by Sencha internally to test Ext JS itself). Since Siesta knows a lot about Ext JS you can write expressive tests using Component Query instead of CSS and get much more robust test compared to simpler tools described in other answers in this thread. Here's a sample test script in plain JS:
t.chain(
{ click : ">>textfield[name=user]" },
{ type : "Mike[TAB]Password" },
{ click : ">>button[name=loginbutton]" }
);
DISCLAIMER: I work for the company that created it.
http://www.bryntum.com/products/siesta/
Are you looking to do a straight functional test of your web page or are you looking to narrow your tests specifically to the JavaScript in ExtJS?
If it's the former (functional at the UI level), then WatiN/Watir/Webdriver ought to work for you. (If they're not working then I'd love to get more details around specific issues you're running in to.)
If it's the latter then you might investigate Jasmine which gives a lot of interesting capabilities around unit testing your JavaScript at the UI layer.
(If it's functional testing, you might also check out Telerik's Test Studio for functional automation. I'm the Evangelist for that tool, so I'm a bit biased...)
You may want to look at RIATest.
Version 5.0 fully supports ExtJS testing. ExtJS UI widgets are first class citizen in RIATest. This means that unlike other HTML testing tools you do not need to write tests that manipulate the HTML DOM elements. The tests in RIATest operate in terms of ExtJS UI widgets.
Examples of RIATest scripts that work with ExtJS widgets:
The following clicks on an ExtJS button with label "Next Page":
ExtButton("Next Page")=>click();
And the following does drag-n-drop of a row from one ExtJS tree to another:
ExtRow("Controller.js")=>dragAndDropTo(ExtTreePanel("#tree2")->ExtRow("Custom Ext JS"));
And this collapses the header of an ExtJS box:
ExtBox("Feeds")->ExtHeader("FeedsВ")->ExtCollapser()=>click();
(All sample code above is from real test scripts that run on ExtJS sample applications).
RIATest also knows when to automatically wait for ExtJS AJAX to finish, so if your UI does dynamic content downloading the tests will auto-magically wait until data is received from server.
(Disclaimer: I am a RIATest team member).
Sahi is an automation and testing tool I have recently come around as I am in a similar search as you... Selenium hasnt worked for me (as it hasnt for many around the web... havent found anything to make it work... dynamic IDs and other Ext related particularities mess with it apparently)...
take a look at sahi maybe it will be useful... www.sahi.co.in (I have no relation, I discovered it recently and found it useful).
You want to do Functional Testing. Selenium is a good choice. It has API implementations in a slew of languages (Java, Ruby, Python) and it uses Webdriver under the covers.
Ranorex can handle Ext-Js as well, although turning it into first class citizens will require some custom coding. The secret in general is to avoid using id's for object recognition, as they change around and use innertext property instead.
Personally found using xpath with extjs flaky in places.
You're better off (in Java) writing a method which uses a JavaScript component query to pull out the element id. (if it has one)
Can anyone give me examples of large-scale JS apps (including AJAX, different UI widgets, and a sophisticated architecture) with unit tests?
I'm not talking about Selenium tests here, just plain ol' stupid unit tests using mocks, decent result reporting and such.
Not sure why people voted to close, or downvoted the question. Maybe a comment would be nice.
Seriously, I've been trying hard to find unit tested web apps, since I'm having a hard time building mocks and I wonder if it's even possible with reasonable effort. It made me think about the benefits of unit tests on widgets as compared to Selenium tests. People are babbling a lot about unit tests in theory but evidently nobody actually has done it in JS-RIAs. Or have they?
Personally I like Qooxdoo, check it out for your self and see if this is what you want
http://qooxdoo.org/demo#real-life_examples
This is one good tool: http://www.uize.com/
You should look at Jasmine & Sinon.js : http://sinonjs.org/
Here is a good tutorial on testing using Backbone.js, Jasmine & Sinon.js : http://tinnedfruit.com/2011/03/03/testing-backbone-apps-with-jasmine-sinon.html
I also recommend Phantom.js for integration testing... It's a headless browser and much faster than using Selenium... http://www.phantomjs.org/
Btw here is an example of unit-tested app from Pivotal : https://github.com/pivotal/cimonitor. You can find client-side tests there -> cimonitor/public/javascripts/js-common
I'm not sure if this answer will qualify but I'm working on the next iteration of my pet project "Atomic OS" (an OS-metaphor for web developers) which will, eventually, meet your criteria.
I'm working on a related project (which I can't share just yet) that is built on a bare-bones Atomic OS v2 foundation and provides a rich set of UI widgets for mobile web apps.
I built & use JSDog to produce documentation from a subset of JSDoc syntax and unit test runners with QUnit.
For an example of where I'm intending to go with unit tests, please see the Atomic OS documentation. (Click "Docs" in the taskbar and select a class, such as HxJSFS)
Just one perspective:
I work on a web application that is the front end of a video analytics system. (The back end is typically an IP camera, DVR or video router running a very, very lean, embedded web server.) It uses a number of jQueryUI widgets, allows user to configure the device, create video analysis rules, and draw markup over video frames using canvas elements. I think of it as fairly sophisticated.
We use unit tests (originally written for JSUnit, but now using qunit) for a very limited subset of the code. We have unit tests to verify the behavior of business objects, including the ability to serialize/deserialize to/from XML. And we have unit tests to test the basic geometry classes we've written for the canvas markup.
However, we have no unit tests that manipulate the DOM or that verify that the elements on a page are in the correct state. Doing that correctly struck us as too difficult a problem to solve, so we rely on Selinium tests to verify that a given set of inputs will put the DOM into the correct state.
I've been developing a Rails application and I've decided to implement a mixture of Test Driven Development and Behavioral Driven Development.
However the application I am building uses a web application user interface framework known as MochaUI which is built on top of the Mootools framework.
I have just finished writing a portion of unit tests and have moved on to testing the user interface; which is where I start to run into problems.
A lot of the things I want to test is content that is loaded via javascript, some data is loaded into iframes, some data is loaded into elements (ajax).
So I wrote a test
And I should see "Some text loaded into an iframe with javascript"
And as you guessed, it failed. I don't know where to begin to fix this problem, as I am very new to TDD and BDD but I'm working my way there, can anyone give me some pointers or possibly a solution so I can sleep at night?
Thanks!
There is selenium for javascript-testing... Maybe this would be a tip?
see http://github.com/aslakhellesoy/cucumber/wiki/Setting-up-Selenium
or
http://bddcasts.com/series/tools/episodes/using-selenium-with-webrat-and-cucumber
Use capybara, tagging the scenarios that require javascript with #javascript.