Skip navigation

Tag Archives: kids always test your code. thoroughly.

Ever since I took it to heart to write unit tests for my code, I’ve wondered how to unit test frontend functionality. Some will say (and this I remember from my early readings on unit testing) that frontend is not meant to be unit tested but, instead, should be end-to-end tested but I respectfully disagree.

(I’d admit though, that I’ve never groked the difference between unit tests and end-to-end tests. They’re all tests to me in that they ensure my implementation is up to spec and that my changes did not break existing functionality. The last part has saved my ass so much for Chess Templar.)

I disagree because frontend code has features that lends itself well to being a unit-testable component. Among them:

  • Creating DOM objects is creating objects. You should be able to assert the properties of the created objects given parameters x and y.
  • Frontend validation. You should be able to assert how your validators behave. All the more true as your validation logic becomes more complicated.
  • It is not uncommon to have a util.js file. These are utilities, possibly used across multiple files and by multiple developers. It better be tested!

Disappointingly, Javascript has remained trapped inside browsers. Sure enough, Node and company are working to do justice on that but the fact remains that not everyone is using Node and company and so their Javascript remain trapped inside browsers.

And it seems that learning how to unit test in Javascript is largely dependent on how you use Javascript. Are you using plain old jQuery? AngularJS, maybe? For my intents and purposes, I’m on plain old jQuery.

It shouldn’t come as a surprise then that I ended up choosing QUnit as my unit testing library. The docs are easy-to-understand enough. With that, you’ll be testing your Javascript in no time!

But then comes the part of automation. The project I am using this for is, quite frankly, small in scope and it would not cost me much neurons to keep in mind to fire up the HTML page of a test-runner I got from reading QUnit’s docs every time I modify my scripts. But a good programmer is a lazy programmer. So I tried to automate that the tests run at Travis as well1.

The easiest guide I can find comes from this StackOverflow answer. The answer assumes an Ant project and the original question is even for Atlassian Bamboo. However, with a few tweaks, I got it to work with the free set-up the internets afford me.

First, you’d have to install xvfb in your environment. Xvfb is crucial for making your tests headless—I’ve actually first encountered it when trying to automate Selenium tests.

What’s fantastic with CIs (done properly) is that your code gets a fresh instance to run on everytime. Though that also means setting up (meticulously) everytime as well; this means ensuring that xvfb and other dependencies like Firefox or a MySQL instance is running before your tests are ran. To do that in Travis, I had the following in my .travis.yml:

language: python
    - "2.7"
before_script: "pip install -r test-requirements.txt"
install: "pip install -r requirements.txt"
script: "nosetests --with-xcoverage && ./run_js_tests"
    - sudo apt-get update -qq
    - sudo apt-get install -y xvfb
    - sudo apt-get install -y firefox
    - sudo apt-get install -y mysql-server
    - sudo /etc/init.d/mysql start
    - sudo apt-get install -y mysql-client
    - mysql -uroot -e "CREATE DATABASE alexandria_test;"


  • I had to install with the the -y flag. This automatically answers “yes” to all installation-related queries.
  • I had to start mysql manually.
  • I also need to create the test database manually. A few years ago I would be very uncomfortable with the hard-coded test DB name; I would want it to get the name from my config.

Next, we’re using JS Test Driver. There are a couple of Javascript libraries JAR file in the Google Code repo I linked that you need. If you are using git (as I am) and would prefer to submodule, I had the repo ported to git here. I have not yet found the time to submodule since my goal was just to get the set-up working properly.

Having all the required libraries, all the rest are just some configuration. The main call would then be,

java -jar ../lib/JsTestDriver.jar --config jsTestDriver.conf --port 4224 --browser $FIREFOX --tests all --testOutput $OUTPUT_DIR

Where --port is as configured in jsTestDriver.conf and $FIREFOX is the path to the local Firefox installation.

Next come the actual unit tests. If you have followed thus far, you should be able to see some logs related to Javascript tests in your CI server. However, if you followed QUnit’s documentation as it stands (and be able to run your tests from an HTML page test runner), you might notice that your CI reports of 0 tests found and 0 tests ran.

This is because the QUnitAdapter library in JS Test Driver features a different organization than the actual QUnit library. I had to modify my unit tests as in this commit. But in summary:

  • Don’t refer from QUnit. QUnitAdapter provides window-level (read: global) functions that are analogous to QUnit’s. So QUnit.test becomes test and QUnit.module just becomes module.
  • Similarly, forego the asserts. A notable exception is the equality assertion. QUnit’s assert has it as equal while QUnitAdapter has it as equals.
  • beforeEach becomes setup. Self-explanatory.

I figured this out because I read the source code of QUnitTestAdapter. There might be more quirks I haven’t found out yet but these should be enough to get you to testing functionality; the unit test code might not be as idiomatic as desired but hey, it works.

I’m still far from my ideal unit testing set-up for Javascript. All I’ve managed to achieve in this post is to get the tests to run in a CI environment. Notably, test failures for Javascript do not affect the result of the build. I’d also want to get the Javascript included in the coverage reports. And, maybe, reconcile QUnitTestAdapter with the actual constructs of plain QUnit.

  1. Interesting to note that jQuery does not have CI badges on its repo and that they use Node to automate. []

Note: My thesis is done. However, there are still some things which I find of interest to address here. Due to how our thesis was (mis)handled, I’m only finding the time to post about these things now.

Last time, I told you how we are porting all our Matlab/Octave code to Java. I wrote about a huge difference between Matlab and Octave’s implementation of rgb2gray. However, as it became apparent to me, my issues with rgb2gray are not quite done yet.

First a little background. Our project relies heavily on the Fast Fourier Transform, a numerical algorithm whose products I bet you encounter everyday though you probably are not aware of it. The 2D FFT is built-in with Octave, as expected for a language meant specifically for mathematical processing. The same, however, cannot be said for Java.

It’d be crazy for me to attempt to code it from scratch due to a number of reasons not the least of which is the fact that I don’t really have a solid training with numerical algorithms. So, after browsing through various libraries, we decided to use JTransforms, largely because we can see the source code for ourselves and it is natively in Java, in contrast to, say, FFTW, which has Java bindings but is natively in C. Plus, it does not have power-of-2 constraints, a common trait among various implementations of the FFT.

Now, the thing is, there seems to be quite a considerable offset between the FFT results of Octave1 and JTransforms; the kind of offset which you’d be so tempted to chalk up to floating-point handling differences though some part of your reason tells you it is too large to be so. The offset I was seeing ranged from 2 to 12 integer values.

As I admitted earlier, I don’t have any solid grounding with numerical algorithms. The way I see it, there are a number of possible culprits on why I’m not getting the results I should get. The FFT, after all, is a blanket term for a family of algorithms which all do the same thing, namely, apply the Fourier Transform to a discrete collection of values (i.e., vectors or matrices).

What I’ve Tried (Or, the scientific probable reason on why there is this offset, as discussed by my adviser)

Warning: Some equations ahead. I wouldn’t be delving too much into the equations and you should be able to understand my main point with just some basic algebra. But just so you know.

Consider this tutorial on the FFT.

It defines the 2D FFT as:

F[k,l] = \frac{1}{\sqrt{MN}}\sum_{n=0}^{N-1}\sum_{m=0}^{M-1}f[m,n]e^{-2\pi i(\frac{mk}{M}+\frac{nl}{N})} f[m,n]= \frac{1}{\sqrt{MN}}\sum_{l=0}^{N-1}\sum_{k=0}^{M-1}F[k,l]e^{2\pi i(\frac{mk}{M}+\frac{nl}{N})} 0 \leq m,k \leq M-1, 0 \leq n,l \leq N-1

where M and N is the number of samples in the x and y direction (or, for our particular problem, the dimensions of the image).

While it may seem interesting to find mutual recursion here, what my adviser told me to note is the constant at the beginning of the equations, \frac{1}{\sqrt{MN}}. According to him, depending on the implementation of the FFT we are using (remember what I told you above that Fast Fourier Transform is just a blanket term for a family of algorithms), the constant varies to either \frac{1}{\sqrt{MN}} or \frac{1}{MN}. It’s now just a matter of scaling the samples (the pixel values) by the appropriate constant to get the desired results.

The tutorial I linked to presents the following sample signal to demonstrate the FFT:

Sample Signal

which should evaluate to the following real and imaginary component respectively

FFT real

FFT imaginary

The following code listing directly translates the above example to Octave code:

x_real = zeros(8, 8);
x_real(2,3) = 70;
x_real(2,4) = 80;
x_real(2,5) = 90;
x_real(3,3) = 90;
x_real(3,4) = 100;
x_real(3,5) = 110;
x_real(4,3) = 110;
x_real(4,4) = 120;
x_real(4,5) = 130;
x_real(5,3) = 130;
x_real(5,4) = 140;
x_real(5,5) = 150
x_fft = fft2(x_real);
x_r = real(x_fft)
x_i = imag(x_fft)

Which results to the following output:

x_real =
     0     0     0     0     0     0     0     0
     0     0    70    80    90     0     0     0
     0     0    90   100   110     0     0     0
     0     0   110   120   130     0     0     0
     0     0   130   140   150     0     0     0
     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0
x_r =
   1.3200e+03  -7.9113e+02   8.0000e+01  -1.6887e+02   4.4000e+02  -1.6887e+02   8.0000e+01  -7.9113e+02
  -5.0485e+02  -9.0711e+01   2.2142e+02   1.0586e+02  -1.6828e+02   1.2721e+01  -2.6142e+02   6.8527e+02
   1.2000e+02   0.0000e+00  -4.0000e+01  -2.3431e+01   4.0000e+01   0.0000e+00   4.0000e+01  -1.3657e+02
  -3.3515e+02   1.3414e+02   2.1421e+01   5.0711e+01  -1.1172e+02   3.4731e+01  -6.1421e+01   2.6728e+02
   1.2000e+02  -6.8284e+01   0.0000e+00  -1.1716e+01   4.0000e+01  -1.1716e+01   0.0000e+00  -6.8284e+01
  -3.3515e+02   2.6728e+02  -6.1421e+01   3.4731e+01  -1.1172e+02   5.0711e+01   2.1421e+01   1.3414e+02
   1.2000e+02  -1.3657e+02   4.0000e+01   0.0000e+00   4.0000e+01  -2.3431e+01  -4.0000e+01   0.0000e+00
  -5.0485e+02   6.8527e+02  -2.6142e+02   1.2721e+01  -1.6828e+02   1.0586e+02   2.2142e+02  -9.0711e+01
x_i =
     0.00000  -711.12698   440.00000    88.87302     0.00000   -88.87302  -440.00000   711.12698
  -724.26407   713.55339  -216.56854    55.56349  -241.42136   134.14214   120.00000   158.99495
   120.00000  -136.56854    40.00000     0.00000    40.00000   -23.43146   -40.00000     0.00000
  -124.26407   255.56349  -120.00000    -6.44661   -41.42136    38.99495   103.43146  -105.85786
     0.00000   -68.28427    40.00000    11.71573     0.00000   -11.71573   -40.00000    68.28427
   124.26407   105.85786  -103.43146   -38.99495    41.42136     6.44661   120.00000  -255.56349
  -120.00000    -0.00000    40.00000    23.43146   -40.00000    -0.00000   -40.00000   136.56854
   724.26407  -158.99495  -120.00000  -134.14214   241.42136   -55.56349   216.56854  -713.55339

As evident, the results are very far from what our source says. However, dividing the sample (matrix x_r) by 8 (cf sample size) produces the results as given by our source.

Add the following line before calling fft2

x_real /= 8;

And we get,

x_r =
   165.00000   -98.89087    10.00000   -21.10913    55.00000   -21.10913    10.00000   -98.89087
   -63.10660   -11.33883    27.67767    13.23223   -21.03553     1.59010   -32.67767    85.65864
    15.00000     0.00000    -5.00000    -2.92893     5.00000     0.00000     5.00000   -17.07107
   -41.89340    16.76777     2.67767     6.33883   -13.96447     4.34136    -7.67767    33.40990
    15.00000    -8.53553     0.00000    -1.46447     5.00000    -1.46447     0.00000    -8.53553
   -41.89340    33.40990    -7.67767     4.34136   -13.96447     6.33883     2.67767    16.76777
    15.00000   -17.07107     5.00000     0.00000     5.00000    -2.92893    -5.00000     0.00000
   -63.10660    85.65864   -32.67767     1.59010   -21.03553    13.23223    27.67767   -11.33883
x_i =
    0.00000  -88.89087   55.00000   11.10913    0.00000  -11.10913  -55.00000   88.89087
  -90.53301   89.19417  -27.07107    6.94544  -30.17767   16.76777   15.00000   19.87437
   15.00000  -17.07107    5.00000    0.00000    5.00000   -2.92893   -5.00000    0.00000
  -15.53301   31.94544  -15.00000   -0.80583   -5.17767    4.87437   12.92893  -13.23223
    0.00000   -8.53553    5.00000    1.46447    0.00000   -1.46447   -5.00000    8.53553
   15.53301   13.23223  -12.92893   -4.87437    5.17767    0.80583   15.00000  -31.94544
  -15.00000   -0.00000    5.00000    2.92893   -5.00000   -0.00000   -5.00000   17.07107
   90.53301  -19.87437  -15.00000  -16.76777   30.17767   -6.94544   27.07107  -89.19417

Which, at last, agrees with our source.

The Blooper (or, the actual and embarassing reason why JTransforms FFT is not coinciding with Octave FFT)

In my first post about rgb2gray, I mentioned that I was taking the floor of the average of the RGB components of a pixel (or, in Java code, just perform integer division as the resulting precision loss is tantamount to floor). Big mistake. Octave does not merely floor values. It rounds off values.

In code, so there be no misunderstandings,

public static int[][] rgb2gray(BufferedImage bi) {
  int heightLimit = bi.getHeight();
  int widthLimit = bi.getWidth();
  int[][] converted = new int[heightLimit][widthLimit];
  for (int height = 0; height < heightLimit; height++) {
    for (int width = 0; width < widthLimit; width++) {
      Color c = new Color(bi.getRGB(width, height) & 0x00ffffff);
      float rgbSum = c.getRed() + c.getGreen() + c.getBlue();
      float ave = (rgbSum / 3f);
      float diff = ave % 1f;
      int iave = diff < 0.5f ? (int) ave : (int) (ave + 1);
      converted[height][width] = iave;
  return converted;

The moral of this long story? If two supposedly-similar functions are returning different outputs, check that the inputs are exactly the same before jumping to any wild conclusions.

  1. I’d like to note here that, according to the help file, Octave’s FFT is based on FFTW []