I'm looking for framework which provides unit tests for JS. Later, I'll have to integrate it with CruiseControl.NET. I have a lot of asp websites using JS and I need to automate testing for them. For example I used local JSUnit (may be other framework), which was quite easy for me, but I have no idea how to integrate it with CC.NET. Maybe you can show me how to start with ?
NOTE: it must be CC.NET, framework for unit test not specified
I realize this is a rather old question, but I have had similar interests so I figure I would post an answer regardless. I am assuming you are writting OO style JavaScript and wanting to test those objects.
A common solution recommended by people is to run JsTestDriver and this is definitely a great tool; that being said, it requires the JVM to be installed on your machine as well as the build server. In addition to requiring the JVM, JsTestDriver is still dependant on running one or more 'Slave' browsers. Personally, I believe that should not be a concern when unit testing JavaScript objects. If the focus is UI testing, then using a tool such as WatiN and is a different type of test in my opinion. The browser should be mock out like you would mock out any other view using JSMock or JsMockito (which I like best).
To that end, I have used Windows Script Host to run my JavaScript unit tests for years. This has several advantages:
No Browser Required (to me that is a good thing).
CScript is already on every Windows machine since XP; so nothing to install.
Runs in background process and does not require an interactive UI when running tests.
Since running inside MSTest, NUnit or xUnit etc, integrating with CC.NET, Hudson, or TeamCity is as easy as running your unit tests as a part of the build.
Full debug support simply by running your unit test inside the debugger.
There are a couple of disadvantages of course:
The machine running the unit tests has to have the ability to spawn off new processes (CSCript) to actually run the tests (has yet to be an issue).
Slower that running regular unit tests (A little over 1,000/minute on an older dual core if run individually - i.e., not bundled together in a single CSCript process).
Using JSTest.NET (approach I have used for years but just posted online), you end up with a test fixture that may look similar to the following:
using JSTest;
using JSTest.ScriptLibraries;
using Xunit;
namespace JSTest.Sample
{
public class EventDispatcherTests
{
private readonly TestScript _testScript = new TestScript();
public EventDispatcherTests()
{
//Append File(s) Under Test.
_testScript.AppendFile(#"..\..\..\Web\Scripts\eventDispatcher.js");
//Append Mock/Assertion libraries.
_testScript.AppendBlock(new JsHamcrestLibrary());
_testScript.AppendBlock(new JsMockitoLibrary());
//Append Common "Setup" Scripts.
_testScript.AppendBlock(#"var dispatcher = new EventDispatcher();
var mockHandler = JsMockito.mockFunction();
var mockPredicate = JsMockito.mockFunction();
var fakeEvent = { eventType: 'CommentAdded', data: 'Sample Comment' };
");
}
[Fact]
public void ProcessEventInvokesAttachedHandler()
{
...
}
[Fact]
public void ProcessEventGracefullyHandlesPredicateException()
{
_testScript.RunTest(#"var mockPredicateAlternate = JsMockito.mockFunction();
JsMockito.when(mockPredicateAlternate)(fakeEvent).thenThrow('MyException');
dispatcher.attachListener(mockHandler, mockPredicateAlternate);
dispatcher.processEvent(fakeEvent);
JsMockito.verify(mockPredicateAlternate)(fakeEvent);
JsMockito.verifyZeroInteractions(mockHandler);
");
}
}
}
This approach works well for me, and is very simple to setup. Basically, it is like writing regular unit tests, but with JavaScript.
Related
I am brand new to creating unit tests, and attempting to create tests for a project I did not create. The app I'm working with uses python/flask as a web container and loads various data stored from js files into the UI. I'm using pytest to run my tests, and I've created a few very simple tests so far, but I'm not sure if what I'm doing is even relevant.
Basically I've created something extremely simple to check if the needed files are available for the app to run properly. I have some functions put together that look for critical files, below are 2 examples:
import pytest
import requests as req
def test_check_jsitems
url = 'https://private_app_url/DB-exports_check_file.js'
r = req.get(url)
print(r.status_code)
assert r.status_code == req.codes.ok
def test_analysis_html
url = 'https://private_app_url/example_page.html'
r = req.get(url)
print(r.status_code)
assert r.status_code == req.codes.ok
My tests do work - if I remove one of the files and the page doesn't load properly - my basic tests will show what file is missing. Does it matter that the app must be running for the tests to execute properly? This is my first attempt at unit testing, so kindly cut me some slack
While testing is such a big topic, and does not fit in a single answer here, a couple of thoughts.
It's great that you started testing! These tests at least show that some part of your application is working.
While it is ok, that your tests require a running server, getting rid of that requirement, would have some advantages.
you don't need to start the server :-)
you know how to run your tests, even in a year from now (it's just pytest)
your colleagues can run the tests more easily
you could run your test in CI (continuous integration)
they are probably faster
You could check out the official Flask documentation on how to run tests without a running server.
Currently, you only test whether your files are available - that is a good start.
What about testing, whether the files (e.g the html file) have the correct content?
If it is a form, whether you can submit it?
Think about how the app is used - which problems does it solve?
And then try to test these requirements.
If you are into learning more about testing, I'd recommend the testandcode.com podcast by Brian Okken - especially the first episodes teach a lot about testing.
I am developing a JavaScript library (https://github.com/yvesgurcan/web-midi-player) to enable MIDI playback in a web application. The library relies on the Web Audio API to create a way to play these MIDI files (https://github.com/yvesgurcan/web-midi-player/blob/test/src/MidiPlayer.js#L50). However, I am having trouble creating meaningful unit tests with Jest (https://github.com/yvesgurcan/web-midi-player/blob/test/tests/midiPlayer.js) because these tests don't have access to the window object and more particularly to window.AudioContext. As a consequence, running my application code which relies on AudioContext throws errors related to the fact that this object does not exist and I can't actually test very much things in the library.
I've tried the following packages to solve my problem: jsdom, jsdom-global, and also web-audio-test-api but none of these seem to inject AudioContext in the environment.
I am thinking that the solution here would be to stub/mock AudioContext but that does not sound like a good solution for solid unit tests.
What do you folks suggest to test the Web Audio API? Is stubbing the only viable solution here?
I think it depends a bit on what you want to test. Since you're using Jest I imagine you're just interested in testing the correctness of your own code. In that case I would recommend to fully mock the Web Audio API. It's not part of your responsibility and you can assume it works the way it should. The only thing you have to test is if your code is making the expected calls.
Mocking globally available variables like the AudioContext constructor is always a bit tricky but you could allow an AudioContext to be passed into your MidiPlayer class as an optional argument. It would make testing a little easier and it would also allow users of your library to bring their own AudioContext.
I think of something like this:
class MidiPlayer {
constructor({
// ... the other options ...
context = new AudioContext()
}) {
// ...
}
}
Inside a test you could then simply instantiate the MidiPlayer with a fake AudioContext.
const fakeAudioContext = {
currentTime: 3,
// ... and all the other things your code uses ...
};
const midiPlayer = new MidiPlayer({ context: fakeAudioContext });
I recently answered a similar question related to Tone.js which might be helpful. The basic idea is the same.
In case you want to test if your library works nicely with the Web Audio API in a browser I would recommend to use a test runner like Karma. It executes the tests in a real browser and therefore can use all the browser APIs.
I have a series of functions like below, that thread through a web application that simulate login, and then runs through many features of the web app. I am using JS, nightwatch.js, and selenium via browserstack.. the problem is, it all reports through browser stack as one large test with this approach; how could I get each function to report within browserstack as separate test?
this.Settings = function(browser) {
browser
.url(Data.urls.settings)
.waitForElementVisible("div.status-editor .box", 1000)
Errors.checkForErrors(browser);
browser.end();
};
this.TeamPanel = function(browser) {
browser
Errors.checkForErrors(browser);
browser.end();
};
It seems you are using the same remote browser instance for all the test functions which therefore are being run as a single test case on BrowserStack. You need to create a new driver instance before every test function. You can either implement that parallelisation logic in your framework or use any sample nightwatch framework like the one here: https://github.com/browserstack/nightwatch-browserstack
This could be a stupid question. Jasmine, Qunit, Mocha, Unit.js, etc - as far I as I know are Javascript test frameworks. But what is a Javascript test framework? What it is for actually? Is it any different from these Javascript frameworks below?
ember.js
backbone
require.js
Jasmine,
describe('Hello world', function() {
it('says hello', function() {
expect(helloWorld()).toEqual("Hello world!");
});
});
It seems like that is what node.js does, isn't?
What do you need to test?
(Short overview)
A test framework is a set of tools that allows you to test the functionality of your code (in this case your Javascript code).
It allows you to test certain functions and check if the output/result matches your expectations.
They allow you to test certain conditions and how your code react on that, like missing or unset variables, unexpected data in your variables and so on.
And one of the advantages is the test automation. This allows you to run a bunch of test automatically and it will give you result if every single test. This way you can see which test fails after you made some changes in your code.
Also you should consider reading the link mplungjan provided.
(If I missed something mandatory to say, then leave a comment, I will add that)
Has anyone tried integrating Dojo DOH unit-tests with Jenkins?
I'd like to do the following, but don't want to reinvent it if this has already been done. So, I'm thinking:
Kick off the DOH-tests from a post-build step in Jenkins and wait for the results
Run the tests themselves in a headless-browser (e.g. Crowbar)
Parse the succes/error-count from the HTML returned by Crowbar
Find (or write) a Jenkins plugin that will (a) fail the build if there are failing tests, (b) render the test results, (c) possibly integrate results into the CI game plugin
Questions:
Has this been done before?
Do you see any issues with the outline above?
Do you know of a Jenkins plugin that will help, or will I have to build my own?
1. Automated Dojo testing - DOH & Selenium-RC (Rob Coup - 2008/01/03)
Plan:
Have a config file defining which browsers to launch, which machines they're on, and what tests to run.
Launch each browser via Selenium-RC
Run the tests via the normal DOH browser runner.
Use Selenium to extract the results from DOH.
Collate the results from the various browsers and produce something useful.
Solution:
Drop seleniumRunner.js, seleniumRunner.config.js, seleniumRunner.sh (or the .bat if you're on Windows), and selenium-java-client-driver.jar into util/doh/ in your Dojo install.
Put selenium-server.jar on each test machine, then run java -jar selenium-server.jar -multiWindow so it listens for the browser-control messages.
Edit seleniumRunner.config.js and change browsers and rootUrl to match your setup. The rootUrl needs to be reachable from each test machine.
run ./seleniumRunner.sh seleniumRunner.config.js from util/doh/ on your workstation
It'll load the config, fire up the browsers on each machine, run the unit tests from Dojo core, and print the pass/fail/error stats for each.
Each browser is kicked off and monitored in a separate thread (not strictly necessary but too cool to resist doing).
Issues:
unless I ran the selenium server in multiWindow mode Safari and Firefox would pop up Print dialogs (!?!) whenever the test page was
loaded. But Safari never initialised the test page if it was in
multiWindow mode. On OSX and Windows. gah.
Opera on OSX didn't set up the Selenium proxy properly (localhost:4444 for reference).
IE didn't like doing a dojo.connect() via the selenium javascript commands for some reason.
2. Seems reasonable to me.
3. Jenkins Selenium plugin
This plugin turns your Jenkins cluster into a Selenium2 Grid cluster,
so that you can utilize your heterogeneous Jenkins clusters to carry
out Selenium tests. This plugin is a turn-key solution — no additional
installation nor configuration is necessary to make it work. The
plugin installs Selenium Grid on all the slaves automatically and set
up a grid on its own.
For running the D.O.H tests i have developed a tool which integrates into ci and can start the browser.
http://codeblog.bigbrowser.net/dojo-testing-d-o-h-with-continuous-integration/
Maybee you can give this also a try.
I have explained there where to download and how to run it.
Here's how I did it with HTMLUnit. No Selenium required.
It runs as a regular JUnit test (which can easily be run automatically by your CI Server), and prints out the DOH log if there is a test failure.
public class JavascriptTest {
private static final int MAX_RUNNING_TIME = 10 * 1000;
//The test runner
public static final String PATHNAME = "src/main/webapp/library/mystuff/dojo/util/tests/runTests.html";
//Runs all of the Dojo Objective Harness (D.O.H.) javascript tests.
//The tests are currently grouped into test modules, and the parent module is "util.tests.module" (in module.js)
//As you can see in the URL pathname, we pass that module name to the testRunner and it runs all the javascript tests.
#Test
public void runAllJavascriptTests() throws Exception {
final WebClient webClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_8);
final HtmlPage page = webClient.getPage("file://" + new File(PATHNAME).getAbsolutePath());
waitForTestsToRun(webClient, page);
String log = page.getElementById("logBody").asText();
assertTrue(log, page.asText().contains("WOOHOO!!")); //D.O.H. will display WOOHOO!! if all tests are successful.
}
private void waitForTestsToRun(WebClient webClient, HtmlPage page) {
webClient.waitForBackgroundJavaScript(500);
int runningTime = 0;
while(testsAreRunning(page) && runningTime < MAX_RUNNING_TIME){
webClient.waitForBackgroundJavaScript(500);
runningTime += 500;
}
}
private boolean testsAreRunning(HtmlPage page) {
//Check if the "Tests Running" div is visible.
return "".equals(page.getElementById("playingMsg").getAttribute("style"));
}
}
And below is the content of runTests.html. It basically just redirects to the DOJO test runner, with parameters specific to the tests in the directory we want to test.
It's just a nice way to structure things, you could alternatively have specified this URL in the PATHNAME field in the JUnit test.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Dojox Unit Test Runner</title>
<!--The "testModule" param tells the runner which test module to run-->
<!--The "paths" param adds our dojo module paths, otherwise it would just look in the default dojo modules for code to test.-->
<meta http-equiv="REFRESH" content="0;url=../../../../dojo-release-1.7.2-src/util/doh/runner.html?testModule=util.tests.module&paths=util,../../mystuff/dojo/util;mystuff,../../mystuff/dojo"></HEAD>
<BODY>
Redirecting to D.O.H runner.
</BODY>
</HTML>