t7zm7q
Last Updated: February 25, 2016
·
577
· whyi

Unittesting Processing.js project with Jasmine

I've been using Jasmine for unit testing my project written with Processing.js

Consider the following Processing.js code,

void setup() {
  size(200,200);
}

void draw() {
  ellipse(100, 100, 50, 50);
}

which looks like

Picture

And let's suppose we want to unit test the draw() method, which is not so obvious.

The sketch folder looks like this at the moment:

$ ll
total 19
drwxr-xr-x    1 jeonggyu Administ     4096 Nov 26 11:14 ./
drwxr-xr-x    1 jeonggyu Administ    32768 Nov 26 11:08 ../
-rw-r--r--    1 jeonggyu Administ       82 Nov 26 11:14 codewall.pde
-rw-r--r--    1 jeonggyu Administ       67 Nov 26 10:53 sketch.properties
drwxr-xr-x    1 jeonggyu Administ        0 Nov 26 11:15 web-export/

If you don't have the web-export folder, please run the code at least once in the Processing IDE, that will create it.

The first thing to do is copy the latest Jasmine into the Processing sketch folder.
I went to https://github.com/jasmine/jasmine/tree/master/dist and downloaded the latest version. Then I extracted and copied it over to the sketch folder.

Finally I renamed it to tests such that the sketch folder should look like:

$ ll
total 21
drwxr-xr-x    1 jeonggyu Administ     4096 Nov 26 11:22 ./
drwxr-xr-x    1 jeonggyu Administ    32768 Nov 26 11:08 ../
-rw-r--r--    1 jeonggyu Administ       82 Nov 26 11:14 codewall.pde
-rw-r--r--    1 jeonggyu Administ       67 Nov 26 10:53 sketch.properties
drwxr-xr-x    1 jeonggyu Administ     4096 Nov 26 11:22 tests/
drwxr-xr-x    1 jeonggyu Administ        0 Nov 26 11:15 web-export/

And the tests folder has the Jasmine SpecRunner.html

$ ll tests
total 6
drwxr-xr-x    1 jeonggyu Administ     4096 Nov 26 11:22 ./
drwxr-xr-x    1 jeonggyu Administ     4096 Nov 26 11:22 ../
-rw-r--r--    1 jeonggyu Administ     1061 Nov 16 14:52 MIT.LICENSE
-rw-r--r--    1 jeonggyu Administ      703 Nov 16 14:52 SpecRunner.html
drwxr-xr-x    1 jeonggyu Administ        0 Nov 26 11:22 lib/
drwxr-xr-x    1 jeonggyu Administ        0 Nov 26 11:22 spec/
drwxr-xr-x    1 jeonggyu Administ        0 Nov 26 11:22 src/

Now, we need to modify the SpecRunner.html to have the running Processing.js instance.
The way I did is I brought many pieces of code from the* web-export/index.html* as you can see in the following steps:

Open the SpecRunner.html in the text editor.

First, let's include the processing.js dependency.

<!-- dependencies for our sketch -->
<script src="processing.js" type="text/javascript"></script>

Second, let's include the spec files (which we haven't created yet).

<!-- include spec files here... -->
<script src="spec/codewallTests.js"></script>

Third, we need a small helper method to use in the spec. This is also from the web-export/index.html

<script type="text/javascript">
// convenience function to get the id attribute of generated sketch html element
function getProcessingSketchId () { return 'codewall'; }
</script>

And finally, the canvas. Note the style="display:none" to avoid having the canvas showing up in the SpecRunner.

<div style="display:none">
  <canvas id="codewall" data-processing-sources="codewall.pde" width="1" height="1" style="display:none">
    <p>Your browser does not support the canvas tag.</p>
    <!-- Note: you can put any alternative content here. -->
  </canvas>

  <noscript>
    <p>JavaScript is required to view the contents of this page.</p>
  </noscript>
</div>

Don't worry about the paths are not corresponding, as we will create a little script to deal with it.

Before jumping into creating the script let's justify why we need it.

When Processing.js app is running via Processing IDE I've figured that everything under web-export is served.
So the index.html which has the canvas object is what the IDE launches when hitting Ctrl+R.
If the SpecRunner.html is in the web-export folder.. well, that's what we want!

So it looks like this:

Picture

Wait, you might ask why not put the SpecRunner.html and stuff in the web-export in the first place, instead of copying it over from the tests folder.
Good question. The reason is, I've figured that web-export folder got completely overwritten whenever the source code (*.pde files) is modified while the app is running. In order to avoid that I've came up with the script solution. If you have the right fix for this please let me know!

I named the script runTests.sh and placed it in the root of the Sketch folder where all the *.pde files are.
It looks like:

#!/bin/bash
cp -r tests/* web-export
cd tests/spec
jitter . ../../web-export/spec

It has the jitter command at the end to compile .coffee into .js.

jitter can be installed via npm install -g jitter
More information available @ https://github.com/TrevorBurnham/Jitter

Now, let's write some real tests in CoffeeScript.

DEFAULT_LOAD_TIME_FOR_PROCESSINGJS = 100

prepareForProcessingJsTesting: -> true

describe "codewall", ->
  beforeEach (prepareForProcessingJsTesting) ->
    setTimeout( ()->
      prepareForProcessingJsTesting()
    , DEFAULT_LOAD_TIME_FOR_PROCESSINGJS)

  it "should draw an ellipse at (100,100) with radius 50", ->
    @pjs = Processing.getInstanceById(getProcessingSketchId())
    spyOn(@pjs, "ellipse")
    @pjs.draw()
    expect(@pjs.ellipse).toHaveBeenCalledWith(100, 100, 50, 50)

Save this as tests/spec/codewallTests.coffee

The delay, or setTimeout is introduced in order to make sure the Processing.js is loaded up before Jasmine kicks in.
The testing part is obvious. I grab the Processing.js instance then spy on the ellipse method.
Then I call draw() method and finally checks if the ellipse method is called with the expected parameters.

Have the Processing IDE open, run the app by hitting Ctrl+R or clicking the arrow button.

Picture

It should open the browser and show the app.

Picture

Now, open a console and run the runTest.sh

Picture

Then finally go back to the browser where the app is running, and add SpecRunner.html at the end of the browser address bar.
So for example, http://127.0.0.1:57240/SpecRunner.html

Picture

Remember, whenever the code in the Processing IDE changes the entire web-export folder will be smashed.
In that case we need to kill & re-run the runTests.sh, not so handy for TDD, but it works.

Get the entire example @ https://github.com/whyi/coderwall