Dojo Objective Harness testing with Continuous Integration

Have you ever wondered how to do Dojo Objective Harness testing with Continuous integration ?
dRobotReport might just be the right solution for you.
I have seen a lot of hack around solutions using selenium and such kind so i decided to implement something that can send the results back to the server as they happen. So dRobotReport was born!

The project can be found on github
dRobotReport currently requires you to have node.js with a minimum version of 0.6.9 installed

Just clone the project next to your dojo installation

1
2
3
/dojo
/dRobotReporter
/util

Change into the directory where dRobotReporter and start running

1
node runner.js

This will present you with the help output listing all available commands

Then we can run it. I am starting it in manual mode now where i will need to open the browser and copy the URL over.

1
2
3
4
5
6
7
8
9
10
11
12
13
$var/www/~/dRobotReporter: node runner.js -m widget.tests.module -u http://jenkins.iceweasel.local  -B /js/dojo -M widget,/js/dojo/widget -s http://jenkins.local

info: socket.io started

  Server started

  Listening on Port:     8000
  Testing Module:     widget.tests.module
  Running Browser:     iceweasel
  Dojo basePath:     /js/dojo
  Test url:         http://jenkins.iceweasel.local/js/dojo/util/doh/runner.html?testModule=widget.tests.module&registerModulePath=dRobotReporter,/js/dojo/dRobotReporter;widget,/js/dojo/widget&dohPlugins=dRobotReporter/connector&port=8000&server=http://jenkins.local
  Server url:         http://jenkins.local
  Waiting for Connection

Open your browser and copy the “Test url” into the url and let the tests start running!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Connection established

6 tests to run in 1 groups
------------------------------------------------------------
GROUP "widget.tests.apparence.ToggleButton" has 6 tests to run
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BorderWidth.html::widget.tests.apparence.ToggleButton::startup 0 ms
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BorderWidth.html::widget.tests.apparence.ToggleButton::onChange 1 ms
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BorderWidth.html::widget.tests.apparence.ToggleButton::setValue 4 ms
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BorderWidth.html::widget.tests.apparence.ToggleButton::quietSetValue 1 ms
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BorderWidth.html::widget.tests.apparence.ToggleButton::reset 1 ms
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BorderWidth.html::widget.tests.apparence.ToggleButton::disabled 2 ms
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BorderWidth.html 850 ms
------------------------------------------------------------
GROUP "widget.tests.apparence._boiteCss.BoxShadow" has 1 test to run
6 tests to run in 1 groups
------------------------------------------------------------
GROUP "widget.tests.apparence.ToggleButton" has 6 tests to run
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BoxShadow.html::widget.tests.apparence.ToggleButton::startup 5 ms
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BoxShadow.html::widget.tests.apparence.ToggleButton::onChange 3 ms
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BoxShadow.html::widget.tests.apparence.ToggleButton::setValue 3 ms
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BoxShadow.html::widget.tests.apparence.ToggleButton::quietSetValue 4 ms
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BoxShadow.html::widget.tests.apparence.ToggleButton::reset 3 ms
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BoxShadow.html::widget.tests.apparence.ToggleButton::disabled 7 ms
PASSED test: /js/dojo/widget/tests/apparence/_boiteCss/BoxShadow.html 984 ms
------------------------------------------------------------
GROUP "widget.tests.apparence._boiteCss.ComboBox" has 1 test to run
5 tests to run in 1 groups
------------------------------------------------------------
...
...
...
------------------------------------------------------------
| TEST SUMMARY:
------------------------------------------------------------
     172 tests in 35 groups
     13 errors
     2 failures
------------------------------------------------------------
TESTS FOR iceweasel FAILED
------------------------------------------------------------

You will get either tests Passed/Failed which can now be used in your CI environment.

You can also let the dRobotReporter take care of starting your browser by just setting “-b iceweasel” or whichever browser you want to use.

So long!

Share and Enjoy

Posted in Dojo, Methodology | Tagged , | 1 Comment

Google Map enhancement

Dear Google Maps team,

First, I would like to thank you for the amazing work you’ve been doing for all this time!
Google Maps is aa awesome tool both easy to use and powerful.
Yet I have to admit that I am missing one feature :

The ability to draw a line between two points that would rougly calculate the distance and display it close to that line.
I am often using Google Maps to check locations, and distance between two places, and I have often felt that this would be a great addition, especially for someone looking for a flat “not too far away” from his job :)

This tool could :

– allow to draw straight lines between two points, calculate and display the distance just above (under / aside) the line. With the ability to move the distance label manually if you need to look at something under
– allow to draw custom curvy lines between two points, calculate and display the distance just above (under / aside) the line. With the ability to move the distance label manually if you need to look at something under
– allow to set a point, and automaticcaly draw a circle, for example you click on a place, it will be the center of the circle. you left click and maintain mousedown, it will display a circlepassing by that point and having the choosen center, tt would be great to have the distance from circle to center displayed. If you move your mouse it will make the circle bigger or smaller. When releasing the mouse (mouseup) it sets the circle “in stone”.

I believe these would be strong additions to Google Maps and help people looking for flats, cities, quarters around some places, not too far :)

Another nice idea would be the ability to choose a place (click some point on a map) and determine a max estimated transportation time. and Google Maps would display all the areas within that (average max) transportation time, taking into account subways, bus, walking, car, train, etc :)

Hopefully, a Google Maps team member will read this post and think that these ideas could be interesting to add.

Thank you for the great work you are doing,
Best regards,
PEM-

Share and Enjoy

Posted in Random | Tagged , , , , | Leave a comment

Zend Framework 2 official release

Today it is official that Zend Framework has been released. go and check it out on Zend Framework. Kudos and good job to all the developers involved.

Share and Enjoy

Posted in Dojo | Leave a comment

Single Selection on dijit.Tree

You have always wondered how to disable multi-selection on a dijit.Tree?

Search no longer! You have found a solution!

All you need to do is to add the singular property to your tree properties and dndParams :
dndParams: ["onDndDrop","itemCreator","onDndCancel","checkAcceptance", "checkItemAcceptance", "dragThreshold", "betweenThreshold", "singular"],
singular : true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<!DOCTYPE html>
<html >
<head>

    <link rel="stylesheet" href="/_static/dojo/../dijit/themes/claro/claro.css">
   
<script src='/_static/dojo/../dojo/dojo.js' data-dojo-config='async: true'></script><script>require([
    "dojo/ready", "dojo/_base/window", "dojo/store/Memory",
    "dijit/tree/ObjectStoreModel", "dijit/Tree"
], function(ready, win, Memory, ObjectStoreModel, Tree){

    // Create test store, adding the getChildren() method required by ObjectStoreModel
    var myStore = new Memory({
        data: [
            { id: 'world', name:'The earth', type:'planet', population: '6 billion'},
            { id: 'AF', name:'Africa', type:'continent', population:'900 million', area: '30,221,532 sq km',
                    timezone: '-1 UTC to +4 UTC', parent: 'world'},
                { id: 'EG', name:'Egypt', type:'country', parent: 'AF' },
                { id: 'KE', name:'Kenya', type:'country', parent: 'AF' },
                    { id: 'Nairobi', name:'Nairobi', type:'city', parent: 'KE' },
                    { id: 'Mombasa', name:'Mombasa', type:'city', parent: 'KE' },
                { id: 'SD', name:'Sudan', type:'country', parent: 'AF' },
                    { id: 'Khartoum', name:'Khartoum', type:'city', parent: 'SD' },
            { id: 'AS', name:'Asia', type:'continent', parent: 'world' },
                { id: 'CN', name:'China', type:'country', parent: 'AS' },
                { id: 'IN', name:'India', type:'country', parent: 'AS' },
                { id: 'RU', name:'Russia', type:'country', parent: 'AS' },
                { id: 'MN', name:'Mongolia', type:'country', parent: 'AS' },
            { id: 'OC', name:'Oceania', type:'continent', population:'21 million', parent: 'world'},
            { id: 'EU', name:'Europe', type:'continent', parent: 'world' },
                { id: 'DE', name:'Germany', type:'country', parent: 'EU' },
                { id: 'FR', name:'France', type:'country', parent: 'EU' },
                { id: 'ES', name:'Spain', type:'country', parent: 'EU' },
                { id: 'IT', name:'Italy', type:'country', parent: 'EU' },
            { id: 'NA', name:'North America', type:'continent', parent: 'world' },
            { id: 'SA', name:'South America', type:'continent', parent: 'world' }
        ],
        getChildren: function(object){
            return this.query({parent: object.id});
        }
    });

    // Create the model
    var myModel = new ObjectStoreModel({
        store: myStore,
        query: {id: 'world'}
    });

    // Create the Tree.   Note that all widget creation should be inside a dojo.ready().
    ready(function(){
        var tree = new Tree({
            model: myModel,
            dndParams: ["onDndDrop","itemCreator","onDndCancel","checkAcceptance", "checkItemAcceptance", "dragThreshold", "betweenThreshold", "singular"],
            singular : true
        });
        tree.placeAt(win.body());
    });
});</script>
</head>
<body class="claro">
   
</body>
</html>

Share and Enjoy

Posted in Dojo | Tagged , , , , | Leave a comment

Continuous Deployment part 2

I have setup Jenkins now to create a Diamond Shaped Project.
This means i Have a Starting job, several Downstream Jobs and a Finishing Job which aggregates all the results.

I will show you step by step what i have done to achieve this.

Here is a list of plugins which i have installed.

Jenkins GIT Plugin
Config File Provider Plugin
Build Pipeline Plugin
Copy+Artifact+Plugin
Join Plugin
Chuck Norris build Facts!
EnvInject Plugin
Build Name Setter Plugin

We will need to create opt-in Branches as we do not want every push to go through the automated build Cycle.
For this i have followed this tutorial

Setup GIT to be used within jenkins.Navigate to manage Jenkins and follow the settings.

Just Setting where it shall find the git executable.


Setting git globals to recognize Jenkins as a comitter

Once we have this set we can go ahead and create our First Job.

My first job just Downloads and Install Dependencies by using Composer.
This is a new Package Manager which in my opinion is really good. One problem i had here is that every time this job starts, composer would check if new updates have to be installed. I prevented this by creating a small script which checks if the composer.lock file has changed within the repository. You can find this script here

My Project Settings:

Set Project Name

Set Parameters as described in the tutorial earlier for Opt-In Branches

Advanced Project Options

I want all my Pipeline jobs to finish before this Job can start again.

Source Code Management

The url to my repository e.g. ssh://jenkins@gitrepos.com/Project.git

Hit the second advanced before Repository Browser.
I want my branches to be merged on to the master before attempting to build

Optional: Add a gitweb url to see changes in the build information

Build Triggers

Set an Authentication Token as described in Opt-In branches

Build Environment
Here we have some more interesting options. In my earlier post i mentioned that we are using PHING. We have a build.properties file which we do not want to have in the scm as it is unique for every Build or workstation.

I have created multiple Configuration files using the Config File Provider Plugin.
In the section “Manage Jenkins” you should find Managed files if you have installed the plugin.

I am creating different Configurations and saving it as a global configuration file which can be used within any Jenkins job.

Select which configuration file you want to use in this section and in my case i needed to create the build.properties file within the workspace so i let Jenkins copy it to the target “build.properties”. This makes it easier for future slave configuration as you do not have to mess with the workspace using ssh or anything later. Jenkins just handles everything.

The next option “Set Build name” is from the “Build Name Setter Plugin” as when viewing Jenkins you only see a build number, but if multiple people start a build process and everyone is in a queue, no one really knows which branch is currently building or going to be built next. Sadly this does not resolve the problem to see who is next in the queue but makes it easier to identify which branch is currently in progress. I added ${GIT_BRANCH) which is an existing environment variable.

Build
Here i just execute the script i mentioned earlier to start a package update.
Select “Add BuildStep” -> “Execute Shell”

Here we add our downstream jobs to be executed
Select “Trigger/call builds on other projects”

Post-build Actions
Specify the Job which shall run after every downstream Job is completed. This is where i aggregate all my results to get the big picture of what is going on in the Project.

Editable Email notification – here i set who gets the email on which build status. Mostly i just set here to only notify on failure as we do not want to be spammed with mails.

Phew, that was a lot of writing already. Will continue the next job tomorrow. Stay tuned!

Share and Enjoy

Posted in Methodology | Tagged , , , , | Leave a comment