Robert Basic's blog

Archives for January, 2013

Frontend testing with phantomjs and casperjs

by Robert Basic on January 29, 2013.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

I am not usually fond of doing much frontend stuff, but I do like to dable in some javascript from time to time. Nothing fancy, no node.js, coffeescript and the likes for me. I still feel like making applications on the server side, and have the client just show things to the user. If needed some 3rd party javascript library or framework to make my life easier, and that’s about it.

For a while I was reluctant on writing any frontend tests, integration tests, or whatever you want to call them, because, y’know, refresh-click-click-click and the testing is done. Easy. Except when it’s not. From time to time some piece of user interface gets wild on javascript and it turns out after a couple of weeks, half a dozen of bugs reported, and hundreds of refreshes and thousands of clicks, that whole thing becomes tiresome. Thus, I decided to dabble my toes deeper in the waters of the javascript world and try writing some tests for all this.

What I found first is that there’s a lot of testing libraries out there for javascript. Won’t even try listing them all. When I set out for the hunt I knew what I wanted and needed. I wanted a tool that will help me automate all my refreshclicks, or at least to some extent. Tell the tool through my tests: “go to that page, check what and how is rendered, do some things with the UI, test again”. The less dependencies it has on other things, the better. I asked around among people who are bit more fluent in javascript than I am, what are they using and what would they recommend. Not too much to my surprise, everyone recommended a different thing, whatever fits their problem. So I ended up picking the tools that fit my problem.

The tools chosen

The first tool I picked was phantomjs. It’s a “headless WebKit with JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.” (shamelessly copy-pasted from their website). When installing it either download a binary from their website, or compile the source on your own. If you’re on Ubuntu, do not install it via apt-get. It installs some very old version, 1.4 I think, and phantomjs will just scream at you something about some X servers. The binaries are pre-built for any and all systems, so just use them (not that I tried all of them, but I trust they all work).

To cut the story short, writing tests with just phantomjs is difficult. If at all possible. Because hey! It’s not a testing library. I think. This part is a bit blurry for me.

Enter casperjs! These two together look like a perfect match for doing automated, frontend tests full of javascript.

Even though last week on Friday I was being a bit frustrated and a bit more of a dick and said bad things about casperjs over twitter which I shouldn’t have. Sorry. Broken things on a Friday at 5PM can do that to a man.

Examples!

That’s why you’re here, to see some examples. And this example, which, btw, is on Github here, will have a simple login page with a form and a logged in page with some UI elements that you can click around and do stuff! And we’re going to test all that with phatnomjs and casperjs. Just like real life. Cookies included.

When writing tests with phantomjs and casperjs, all one need to do is think in steps. Same simple steps like in the refreshclick procedure. First, open page. Make sure we are on the correct page. Make sure all the elements are there. Click something. Make sure that thing is clicked. Fill in a field. Make sure the field is filled. And so on.

Let’s have a look at the first part of the tests.js file:

casper.start('http://localhost/frontend-testing', function () {
    this.test.assertUrlMatch(/login.php$/, 'Redirected to login page');
    this.test.assertExist("#login_form", 'Login form exists');
    this.fill('#login_form', {
        'email': 'email@example.com'
    }, false); // false means don't autosubmit the form
    this.test.assertField('email', 'email@example.com');
});
casper.thenClick('#login', function () {
    this.test.assertUrlMatch(/index.php$/, 'Redirected to index page after login');
});

The tests are surprisingly self-explanatory: start by opening up the home page. Assert that we are (redirected to) on the login page and that the login form exists. Then fill the email field of the login form with a given value. Assert that the field was indeed filled with that value. Once that’s done, then click on the login button, and assert that we end up on the index page.

Easy!

And practically that goes on in the entire test. Start, assert, then do this, assert, then do that, assert, done.

Testing ajax calls isn’t difficult either:

casper.thenClick('#do_ajax', function () {
    this.waitForResource('http://localhost/frontend-testing/ajax.php');
});
casper.then(function () {
    // Sometimes we need to wait a bit more for ajax requests ...
    this.wait(50);
});
casper.then(function () {
    this.test.assertTextExist('Just some ajax response.', 'Ajax request was made');
});

Do some action that triggers an ajax request, wait for that ajax request to finish and assert that something was done with the response from that ajax call. Of course, in real life examples you will have a bit more complicated setup, but hey… As for faking ajax requests I hear that can be done with this cool sinonjs library, but I haven’t managed to get that working, yet. Mostly because I didn’t need to fake any ajax calls.

The most voodoo-like thing in these tests is probably the evaluate() part. I don’t think I really know what that it is, but what I think it is, that, whenever you want to do something in the actual webpage, but from within the tests, you use evaluate().

For example, I had to use evaluate() to determine is the checkbox checked or not:

casper.thenClick('#enable_ajax', function () {
    // I could swear I had this one working
    // this.test.assertEquals(this.getElementAttribute('#enable_ajax', 'checked'), 'checked', 'Checkbox is checked');
    this.test.assertTrue(this.evaluate(function () { 
        return document.getElementById("enable_ajax").checked;
    }), 'Checkbox is checked');
});

Not sure how, but the this.getElementAttribute() way does actually work in my other tests. Honest. Not sure why it didn’t work in this example. Maybe some other factors not present here, affected my other tests? I don’t know.

Helpful bits

What I found extremely helpful while writing the tests is the this.debugHtml() and this.debugPage() casper functions. The former will dump the entire HTML to the terminal, and the latter will dump just the text of the entire page. Can be useful to figure out what’s going on.

The other helpful debugging function I used a lot is this.getElementAttribute(<selector>). It retrieves a bunch of helpful information on an element, which you can then dump to the terminal, to further figure out things:

casper.then(function () {
    require('utils').dump(this.getElementAttribute('#enable_ajax'));
});

Will result in an output like this:

{
    "attributes": {
        "id": "enable_ajax",
        "name": "enable_ajax",
        "type": "checkbox"
    },
    "height": 13,
    "html": "",
    "nodeName": "input",
    "tag": "<input type=\"checkbox\" name=\"enable_ajax\" id=\"enable_ajax\">",
    "text": "",
    "visible": true,
    "width": 13,
    "x": 12,
    "y": 58
}

I mean, it even gives the positions of the checkbox on the page! Super helpful.

casperjs supports CSS3 selectors and, which gives me much joy, XPath. Makes getting those pesky little elements covered in layers of divs and tables a walk in the park.

One thing though: you can’t do things like selecting multiple elements at once and then .each()‘em or something like that. You have to select elements one by one and do assertions on each of them. Even if the selector matches multiple elements, it will just return the first element, so you’ll probably end up using lots of :nth-child(n) selectors. But that’s what copy-paste was invented for.

That’s about it, I guess. Of course, there’s much more to both phantomjs and casperjs, but I found the documentations well written, so I believe it’s fairly easy to tackle even the testing of more complicated web pages with these libraries.

Happy testing!

Tags: automating, casperjs, frontend, javascript, phantomjs, testing.
Categories: Development, Programming.

Need help on your PHP projects? Let's talk!

Gnucash 4.2 with SQLite3 on GNU/Linux

by Robert Basic on January 22, 2013.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

For a while I was trying to figure out how to convert the Gnucash XML file to an SQLite3 database. From version 4.2, Gnucash supports PostrgreSQL, MySQL and SQLite3. Since then, the conversion is apparently simple as choosing File -> Save As … and picking a different data format. Thing is, my Gnucash instance didn’t have that! After some google-fu, turns out I was missing a library called libdbi-dbd-sqlite. After installing the missing library, suddenly the save works as it should. Why Gnucash didn’t pull this dependency (even if it’s optional) when I first installed it, is beyond me. But it’s there now and I can be on my marry way to draw fancy graphs with all this easily accessible, sweet data.

Tags: gnucash, sqlite3, xml.
Categories: Development, Software.

Need help on your PHP projects? Let's talk!

A monkey with a banana

by Robert Basic on January 08, 2013.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

From time to time I browse through the local board shop’s website, especially the “Longboard” section, because, well, I have recently developed this passion for longboarding. Few weeks back, just sometimes before Christmas, I was doing the same. Just casually browsing around, nothing that would catch my interest. And then, there it was, at the bottom of the page. A banana board. “Oh my, a real beauty”, I thought to myself. The price was also in the affordable range. But, a problem was that I really couldn’t, justify to buy it.

Whenever I find something to buy for myself, I really give it a lot of thought and wait for a while, just to see if I really need it. Doing my best to avoid buying stuff in the heat of the moment, which prevents me from having lots of regretable purchases. And it works quite well, can’t think of anything that I regret ever buying. It’s also a very good tactic for saving money.

And after giving it a lot of thought, going to the board shop a couple of times to check it out (sadly, I haven’t seen it, as they didn’t have it in the Novi Sad store, they’d have to order it from their central shop in Belgrade), and giving it some more thought, I finally broke down last week and ordered the board. The fact that they introduced an additional 20% discount around new year’s, also helped with this decision.

Luckily, the ordering time was just two days, so when I placed the order on Thursday, I was to pick it up on Saturday. Marvelous, getting a new board in the middle of a weekend. Even the weather forecast was looking good, not so cold, and dry, even if it’s beginning of January.

Fast-forward to Saturday noon-ish and me being told that the board is actually in Novi Sad, but in the distribution center, and they won’t be delivering it to the shop, as the delivery center doesn’t work on that specific Saturday, but only on Tuesday. Something about having a second Christmas in Serbia and people not working during those days (the orthodox church uses the Julian calendar).

Bollocks.

Tuesday, finally!

And today, just after getting back to the office from the lunch break, the dude from the shop called me, letting me know that the board is in, and that I can come in pick it up after work. “Fuck it!”, I said, “I’ll be there in 5 minutes.”

Once I saw the board, I knew I did a right thing ordering it. It’s just fuckin’ gorgeous! I tried it a little in the shop, paid for it, and hurried out to the streets to give it a test ride back to the office.

It’s fun riding it, extremely fun. It’s much smaller, and feels much different than my longboard. The wheels are smaller, but softer than on the longboard. I was expecting the banana board to be slower, but two-three pushes and it rides like the wind. Oh, and it’s light as a feather!

On slower speeds it’s not really good for making turns, but when going a bit faster the turning is easier. I’m an idiot. I need to loosen up the trucks. The little “buttons” on the top of the board, which are there to provide a good grip whilst riding, are doing their job insanely well. I was pleasantly surprised how good the grip is.

Maybe even a bit too good. While I was riding the board home from the office, the “buttons”, or maybe the bolts from the front truck, under my front foot were bit too hard, and gave an uneasy feel during the ride. Like when you have a tiny rock in your shoe and the damn thing doesn’t won’t to get out. But I’ll try out different stances before giving the final verdict on this.

Apart from this little thing, it really is a fun little board, and I’m happy that I got it. I’ll be mostly using it for quick rounds around the city, and goofing around at the local skate park. Sticking with the longboard for longer rides, cruises, though.

Tags: about, banana, banana board, longboard, random.
Categories: Blablabla, Free time.

Need help on your PHP projects? Let's talk!

2012 - 'twas a fine year!

by Robert Basic on January 01, 2013.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

2012 was a real fine year, filled with travel, friends, work, longboards, books. A couple of beers found their way in my belly, too. The best part is that I honestly can’t remember that a single bad thing happened this year. Most likely because it didn’t. Pure awesomeness.

Can’t really remember what I did from January till March, besides working. Odd. I should probably blog more often (HA!) on the things that happen. Oh well.

April was the month that kicked off the travels for this year. I spent a weekend in Budapest, doing nothing just roaming around the city. I stayed in a 5 star hotel in downtown. Never stayed in a fancy place like that before, and I wanted to try it out. Definitely not my thing, and did get the strange looks from the employees there as I stubmled in in a leather jacket and a military backpack on my back. I probably looked like a hobo. But I had fun and that’s what counts.

May was the month of PHPDay and travelling to Verona with Vranac. I just realised I didn’t blog about it. Well, fuck. We met there some crazy awesome developer dudes from Croatia *waves hi to Luka , Miro and Ivan *. Got to meet Jouzas and Stefan, and be mentored by Patrick, Derick and Rasmus on creating PHP extensions. I even got to get a “You are correct” from Rasmus for a sentence I managed to mutter out. I was giggling like a girl for days after that.

On our way back to Novi Sad, we stopped in Ljubljana to grab lunch with Masa and Swizec. First time meeting them in person, lovely people.

June was a month of work and celebrating one year of Hex!

July was the month of Exit festival in Novi Sad, where I played a host for Swizec, hopefully a good one, as he was staying over at my place. Couple days after the festival, we popped in his car, bought some gas, and of we were to Ljubljana. I stayed there for a couple of days, completely touristy visit, with me roaming around this gorgeous town with a proper paper map in my hands. Bought my first longboard there and found myself in love with a non-geek hobby for the first time in my life. I’d never thought I’ll say this, but sports are fun! Longboarding, at least.

August was spent with me longboarding around Novi Sad. Work and beers were also characteristic for that month.

September started with me going to a mountainboarding event, as a spectator only. I ended up going down this hill. And falling. Twice. I also made a total of over a hundred kilometers longboarding.

In October Jouzas was in Novi Sad for a couple of days. Vranac and I did our best to make his stay enjoyable. Hope we succeeded at that. I ended up shaving my head, whilst having a severe hangover, and making a mohawk. Fun times!

November was the month of Webcamp Zagreb and us travelling to, obviously, Zagreb. And again, I didn’t blog about it. Miro will kill me next time he sees me. The conference was a total success, very well done, even though it was planned and organized in under two months! Eagerly awaiting next year’s event.

After Zagreb I hopped over to Ljubljana (by now you must have realised I’m sorta-kinda in love with that town), where I stayed for a week and worked from the local hackerspace Hekovnik. The rainy weather sucked a bit, and I was hoping I’d get to longboard more, but the one session on Trzin with Swizec was quite enjoyable. I even managed to do my first mini Coleman slide. Hooray!

December was nothing special, just your regular, hard working (or hardly working?) month.

A couple of things I’m not satisfied from the past year is that I didn’t contribute to OSS much and didn’t really learn new things. I also read lot less books than I thought I did - merely some ten-ish books. I’ll just blame “A Dance With Dragons” for that as it took me two or three months to finish it.

As for 2013, there’s no reason really for it to be any less awesomer than 2012. Need to fix and fine tune a couple of things about me, get rid of some bad habits, continue fixing some mistakes from the past and try to be even better to my fellow humans.

Happy New Year and Happy Hackin’!

Tags: about, hex, life, longboard, random, travel.
Categories: Blablabla, Free time.

Need help on your PHP projects? Let's talk!