How to run Dojo DOH unit-tests through Jenkins? - javascript

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>

Related

selenium + chrome.fileSystem.chooseEntry = invalid calling page error

I am writing a Selenium script to test a Chrome app that uses the Chrome.fileSystem.chooseEntry API to select a directory. When I do this manually, it works fine. But when I do this in a Selenium script, I get back this error:
Unchecked runtime.lastError while running fileSystem.chooseEntry: Invalid calling page. This function can't be called from a background page.
Any ideas on how to make Selenium and chooseEntry play nicely together?
I updated to the latest Chromedriver, but still no luck. I also looked at ChromeOptions, but didn't see anything that looked like it would be helpful. The interwebs doesn't seem to have much to say about Selenium and chooseEntry. I'm on version 51 of Chrome.
I'm down to thinking I'll need a special javascript entry point to set the path values for testing instead of using chooseEntry. But I would strongly prefer to not have a separate code execution path for my tests. Anybody have a cleaner solution?
EDIT: per commenter's request, here's the offending code:
chrome.fileSystem.chooseEntry({type:'openDirectory'},function(entry) {
chrome.fileSystem.getWritableEntry(entry,function(writeable_entry) {
console.log("got writeable entry");
});
}, function(e) { errorHandler(e); });
EDIT #2: I've gone with the special javascript entry point hack. In manual mode -- i.e., not running under Selenium -- I run code that executes chooseEntry, and then use the retainEntry API to get the entry id. I added an entry point in my javascript to take an entry id and call the restoreEntry API to turn it back into an entry. I also modified my code so if this entry object is set, then use that as the file instead of calling chooseEntry. Lastly, I modified my Selenium script to call the restoreEntry entry point before running the rest of the script.
This is not ideal, since now my test code execution path is somewhat different from my actual live-human-being-at-the-controls code execution path. But at least it lets me use Selenium scripts now. Of course, if anyone can think of a non-horrible way to solve this solution, I'd love to hear about it.
EDIT #3: Per #Xan's comment, corrected my terminology from "extension" to "Chrome App."
I can only offer this horrible hack. For Chrome Apps under OSX I created folder favorites and use Robot keyPress to navigate and select the 'favorite' folders needed for the App. The only possible redeeming factor is that it does mirror a valid/possible actual human interaction with the file interface.
private void selectOSXFolderFavorite(int favorite) {
// With an OSX file folder dialog open, Shift-Tab to favorites list
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyPress(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_SHIFT);
// move to the top of favorites list
int i = 40;
while (i-- > 0) {
robot.keyPress(KeyEvent.VK_UP);
robot.keyRelease(KeyEvent.VK_UP);
}
while (favorite-- > 0) {
robot.keyPress(KeyEvent.VK_DOWN);
robot.keyRelease(KeyEvent.VK_DOWN);
}
// Send an enter key to Select the selected folder
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
}

How to detect the front-end actions at the back-end?

I'm new to JavaScript environment and it's the one running on the system i'm newly at.
We're using GWT for JavaScript.
What is the best way to detect the connections between the back-end processes
and front-end actions? Eg. which back-end method is invoked when "that" button is pressed, tab is clicked,
window is opened, ... .
The only way I can think of is using the debugger and Eclipse search/call hierarchies facilities: keep putting breakpoints
in places where I anticipate will run-- until i hit the spot.
Is/n't there a more efficient way of doing this?
How do other developers do?
I'm a back-end developer.
In a previous system, I put a port monitor-- Fiddler,
saw the contents of the request the FE is sending and went from there.
I'm aware that this is a naive Q-- please bear with me.
TIA.
//======================
EDIT:
the best would be a
debugger-like tool showing the stack-trace, or even the
execution path in any way, telling the back-end methods that are running and/or spawning the threads.
is there such a tool?
The following takes for granted that you are using a decent IDE and that you have imported the GWT project into such IDE. There's some help at the end if this is not your case.
If you know which Java class contains the front-end logic, and the element you're interested in
Find the object representing the element (a Button, a ListBox, whatever) and look at the event handlers attached to it.
Something like this:
//...
#UiField
ListBox myDropDownList;
//...
myDropDownList.addChangeHandler(new ChangeHandler() {
#Override
public void onChange(ChangeEvent changeEvent) {
SomeService.someRPCmethod(... params, callback, ...);
}
});
The SomeService.someRPCmethod method implementation should contain all the backend calls.
If you know the Java class, but not which one of all the buttons is the one you're looking for
Most GWT apps make use of *.ui.xml files which are like a skeleton for the actual web page. This XML files reference the actual Java objects used in the Java class, and are usually named like the class they represent.
Locate the ui.xml file and look for something like this:
...
<g:ListBox ui:field="myDropDownList" styleName="cssClassName"/>
...
This should appear in your webpage like this:
<select class="cssClassName" ...>
<option ...>
The position inside the XML file, and the CSS class name, should help you pinpoint the element you're looking for. Once you find it, the ui:field attribute points to the Java object (try ctrl+clicking it in your IDE).
Now you just have to look at the handlers as explained before.
If you don't know the Java class which contains the front-end logic
To find the Java class for a given webpage, you can resort to the good ol' string search.
Locate a not-so-common string literal used in the web page. Not something like "Add" but more like "User registration".
Use your IDE to search the project's code base for that string. It should appear inside a .properties file, or a class with constants and literals, or maybe even hardcoded inside the front-end Java class.
Now just use your IDE to follow the references. It might be something like .properties file -> Constants interface -> .ui.xml file -> front-end Java class, or literals Java class -> front-end Java class.
If you don't have access to the front-end source code
You can try to use your Developer Tools / Fiddler to look for REST calls, which is how GWT implements RPC.
So the call to SomeService.someRPCmethod above might appear in Fiddler as a http:://yourwebpage/somepath/SomeService call with a bunch of GET/POST parameters, one of which should be someRPCmethod (the method's name). But this is not always the case.
If you're running GWT 2.6+ in SuperDev mode with Sources enabled, you can also try to debug the Javascript in the front-end until you reach the RPC calls. See abhinav3414's answer.
Last (or maybe first!) resource
Ask the front-end developers, they put the calls in there and can get you on track in minutes ;)
I had similar issue, so I installed an extension in my chrome.Below is the name of the extension. You can try once.
Visual Event 2.1
Know what event is bound on each dom element
There is one more approach, You can debug your code from front end. You can inspect element in your browser and then open Source tab.
Press ctrl + P to search the file in which you want to put the debug points.
Put debug points by clicking on the row number.
This way you need not to go to eclipse that often.
I would start by searching the code for the listeners of whatever events you are interested in and go from there. I work in EXT JS and I do this all the time.
Following all code paths through is the only guarantee unless all calls to the backend go through some known class.
Monitoring the network is also a good way to go.
This can be done in Chrome through the "Developer Tools" on the Network tab.
In GWT you have on the client side "import java.util.logging.Logger;" which output your debug info to the browsers console. On the server side you just use "System.out.println("debug");" for debugging which goes to the Apaches Tomcat log files. Which makes debugging on a live server a bit easier.
GWT uses RPC's for communication between the client and server. The data sent is serialized and can be a whole class if needed. The three folder for source in a module as 'client', 'server' and 'shared'.
For example a shared class used for sending data back and forth: (The blank constructor is required to serialise the class)
public class MySharedData implements Serializable {
private static final long serialVersionUID = 1987236748763652L; // used for serializing data
public List<String> lotsOfStrings = new ArrayList<String>(); // use most java vars
public int width, height;
public MySharedData() {} // 'need' a blank constructor
public MySharedData(MySharedData data) { //do stuff } // also can
}
On the server side it may look something like this:
public class MyServerRPCImpl extends RemoteServiceServlet implements MyServerRPC {
private static final long serialVersionUID = 4435555929902374350L;
public List<String> getStringList(int var, List<String> strs) {
// do stuff
System.out.println("debugging output"); // to tomcat log file
return stringList;
}
}
The client will use an Asynchronous callback with two methods, onSuccess() and onFailure() so you can handle call failures. To use this is something along the lines of:
public class MyGWTApp implements EntryPoint {
// the server RPC class
final MyServerRPCAsync server = GWT.create(MyServerRPC.class); // create RPC instance
final Logger log = Logger.getLogger("tag");
public void doSomething() {
MySharedData data = new MySharedData();
server.getStringList(data, new AsyncCallback<List<String>>() {
#Override
public void onFailure(Throwable caught) {
log.info("error"); // logging goes to the javascript console output
}
#Override
public void onSuccess(List<String> result) {
log.info("call worked");
}
};)
}
}
The above is my way of managing logging as my projects have to run straight from a Tomcat server. I also believe the server logging when run from Eclipse will go to Eclipse's console log, but I'm unsure on that. All server output and errors, including stack traces will be in the /var/log/tomcat/ folder on linux, or the equivalent on Windows. I can honestly say, I've yet not used breakpoints debugging with GWT.
Client and server code is in separate classes in their own folders within the project.
Just want to mention that sometimes debugger is used in situations where other tools can also help (not sure if this is the situation here - but bear with me just another two sentences):
(1) you can grep the relevant html asset , grep is a wonderful tool to learn large systems
(2) you can add log , in some cases you can switch to debug mode and see tons of log traces
Use Network tab in developer tools of your preferred browser you are using to test.
CHROME
Press F12 or alternatively choose from menu - tools > developer tools
FIREFOX
Press F12 or alternatively choose from menu - Developer > toggle tools
IE
Press F12

How do I change the underlying Phantomjs object settings using Chutzpah?

We have some QUnit javascript tests running in Visual Studio using the Chutzpah test adapter. Everything was working fine until we changed our api (the one being tested by the js files) recently, and added some validations over the UserAgent http header. When I tried to update the tests to change/mock the user agent I realized it was not directly possible even by overriding the default browser property.
After a few days of scavenging, I finally found what exactly is happening. Chutzpah is creating a phantomjs page object for the test files to run on. This is being done on a base javascript file (chutzpahRunner.js) located at the Chutzpah adapter installation path. These are the last lines on the file, that effectively start the tests:
...
// Allows local files to make ajax calls to remote urls
page.settings.localToRemoteUrlAccessEnabled = true; //(default false)
// Stops all security (for example you can access content in other domain IFrames)
page.settings.webSecurityEnabled = false; //(default true)
page.open(testFile, pageOpenHandler);
...
Phatomjs supports changing the user agent header by specifying it in the page settings object. If I edit this chutzpahRunner.js file in my machine, and manually set the user agent there, like this:
page.settings.userAgent = "MyCustomUserAgent";
My tests start to work again. The problem is that this is not in the project itself, and thus cannot be shared with the rest of the team.
Is it possible to change the properties of the phantomjs objects created by Chutzpah to run the tests? I'd like to either change them from inside my own tests, or from another script file I could embed on the pipeline.
Without a code change in Chutzpah it is not possible to set those properties on the PhantomJS object. Please file an issue at https://github.com/mmanela/chutzpah asking for this functionality and then fork/patch Chutzpah to add it (or wait for a developer on the project to hopefully get to this).
Update:
I pushed a fix for this issue. Once this is released you can use the following in a Chutzpah.json file:
{
"userAgent": "myUserAgent"
}

JavaScript Unit Testing integrated with CruiseControl.NET

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.

Reference javax.script.ScriptEngine in android or evaluate a javascript expression

Is it possible to reference the javax.script.ScriptEngine library when developing an android application?
If not is there anyway possible to evaluate a javascript expression in android?
For the classes javax.script.ScriptEngine, javax.script.ScriptEngineFactory and so on, you can add the jsr223.jar to your Android project: just copy the .jar file to your libs directory, and add it from Properties->Java Build Path.
These class will allow your JSR 223-compliant engines to compile. You can then do new SomeScriptEngienFactory().getScriptEngine() to get an engine. I've managed to do this with JNLua 1.0.4 and Rhino 1.7R2.
The file jsr223.jar can be downloaded from http://www.java2s.com/Code/Jar/j/Downloadjsr223jar.htm, a direct link is http://www.java2s.com/Code/JarDownload/jsr223/jsr223.jar.zip.
javax.script.ScriptEngine is not a default part of android, but you could easily jar up any libraries you need(assuming the size is reasonable, I'm not sure) and include them in your project.
According to this post, javax.script.ScriptEngine is not available in Android SDK. You can try the steps below to include the library, but the code may not run, even though it will compile.
Using Android Development Toolkit in Windows, I performed the following steps to get javax.script library.
Right-clicked on the project, went to Properties (Project).
Under the Java Build Path, I chose Libraries tab.
Select Add Library located on the middle right of the Tab
Select JRE System Library under Add Library and click Next...
Select Workspace Default JRE (jre 7)
Click Finish.
Click Ok on the Java Build Path to exist project properties.
Javax.script was then loaded.
If you want to evaluate some code in JS in android
1) to your gradle dependencies add (rhino):
compile 'org.mozilla:rhino:1.7R4'
2) write some code like this to get the result of JS evaluation
Context rhino = Context.enter()
// turn off optimization to work with android
rhino.optimizationLevel = -1
String evaluation = "2+2"
try {
ScriptableProject scope = rhino.initStandardObjects()
String result = rhino.evaluateString(scope, evaluation, "JavaScript", 1, null).toString()
} finally {
Context.exit()
}
3) You can write more complex scripts in JS to run in the android app also (functions etc.)

Categories