Tuesday, 8 November 2011

Groovy Geb tests: enabling Javascript for HTMLUnit driver

Ran into a problem where my HTMLUnit driver wouldn't execute Javascript on my pages. Found a simple fix:

import org.openqa.selenium.htmlunit.HtmlUnitDriver
import geb.spock.GebSpec


class TestSomething extends GebSpec {

def setup() {
if (driver instanceof HtmlUnitDriver) {
driver.javascriptEnabled = true
}
}
}


I'm going to stick this in a base class that extends GebSpec that all my test classes can then inherit from.

Thursday, 27 October 2011

Sorting out project's SVN location in Eclipse after moving the project in SVN

Just ran into an issue where I used Subversive's "SVN Repository Browser" view to move a project in SVN back one level. I had this project checked out into my Eclipse workspace, but now it was pointing to a location in SVN that no longer existed.

I could not find a way to change the URL the project was looking for through Subversive. I first tried "Team->Disconnect" on the project, which removed it from SVN. Then, Team->Share Project gives you a dialog to choose the SVN repository URL; however the input field was read-only and I could not change it.

After a little bit of googling, I came across this blog post detailing how to edit the SVN meta data to point to the right URLs.

The script in the comments seemed nice, and trying it out worked great. I'd close the project in Eclipse first just to be safe.

Execute this in the top level of your SVN project:


find . -name entries -type f -exec sed 's@svn+ssh://blah.com/your/old/location@svn+ssh://blah.com/your/new/location@g' -i {} \;

Sorted!

Restoring Ubuntu 11.10's "print screen" behaviour

After upgrading from Ubuntu 11.04 to 11.10, I noticed that the behaviour of the print screen key had changed. Previously, hitting the key would pop up the "Take Screenshot" application, which presented options to grab the whole screen / the current window or to select a region to capture.

In 11.10, hitting print screen simply captures the whole desktop without prompting you for the other options. I often use the 'select region to capture' function to capture screenshots of our websites when reporting a presentation-related bug.

However, I managed to revert the functionality back to the way I liked.

Install compizconfig-settings-manager:
sudo apt-get install compizconfig-settings-manager


You can find it installed into Applications -> Other. Launch the CompizConfig Settings Manager and then check the "Gnome Compatibility" checkbox to enable the plug-in.



Then click the plug-in itself, go to "Commands" and change "Screenshot command line" to
gnome-screenshot -i
The -i flag is for "interactive mode", which prompts you for the type of screenshot you would like to take.



The old functionality is now restored. Brilliant!

Thursday, 20 October 2011

Grails unit tests and metaclass manipulation

There's some information out on Google regarding this issue I just ran into, but I figured a quick blog post can't hurt things :)

Problem:
- Manipulating a class' metaclass will affect that class' behaviour for every test method in that test class.
- We need to be able to remove our meta class changes after every test is executed to avoid test pollution: data setup for one test should not interfere with other tests.

How do we fix this?


import grails.test.*

class StaticClass {
public static String blah() {
return "blah."
}
}

class SomethingTests extends GrailsUnitTestCase {
def testOne() {
def result = StaticClass.blah()
assertEquals("blah.", result)
}

def testTwo() {
StaticClass.metaClass.'static'.blah = { "test" }
def result = StaticClass.blah()
assertEquals("test", result) // test pollution
}

def testThree() {
registerMetaClass(StaticClass)
StaticClass.metaClass.'static'.blah = { "something" }
def result = StaticClass.blah()
assertEquals("something", result)
}

def testFour() {
def result = StaticClass.blah()
assertEquals("test", result)
}
}


By extending GrailsUnitTestCase, we can call "registerMetaClass" (which unfortunately is not available in GroovyUnitTestCase) and pass the class name that we will be performing metaclass changes on. Grails will then automatically revert any metaclass changes that happen to this class after every test.


Important note: you must call this.setUp() if you define a setUp() method in your test case.

You can see in testTwo that the static metaclass change in testOne has persisted between tests. In testThree we do the regsiterMetaClass magic, which then resets the static method's return value to what we previously overwrote it with in testOne.


class AFewOtherTests extends GrailsUnitTestCase {
def testOne() {
registerMetaClass(StaticClass)
StaticClass.metaClass.'static'.blah = { "test" }
def result = StaticClass.blah()
assertEquals("test", result)
}

def testTwo() {
def result = StaticClass.blah()
assertEquals("blah.", result)
}
}

Friday, 12 August 2011

Work experience pt.2

My 3 week placement with Digital-Morphosis is now drawing to a close. Over the 3 weeks I have been introduced to many new languages and software patterns and learnt a number of new techniques. My project is now very functional and has taught a lot about web based development.

I have thoroughly enjoyed my time with Digital-Morphosis and hope to stay in contact with them in the future.

Thursday, 28 July 2011

Work Experience

I approached digital morphosis regarding a work placement towards the end of the academic year. Currently in year 12, I have recently sat my AS levels and am aspiring to apply to university to study a degree in Computer Science. Deciding a work placement in a real life company would be very beneficial for me, I contacted a number of Software development firms inquiring about a work placement during my summer holidays. Digital morphosis were quick to respond to my email and we set up a meeting for me to come down to their office. During the meeting we agreed on a 3 week placement and I took a look at some of their current projects.

Currently in my first week at digital morphosis, I've been working with Nodejs, an event-driven, server-side javascript environment and MongoDB, a document orientated database. Not having done much web based development, node has been an exciting new experience for me.

I've been allocated a small project which I will be working on for the duration of my placement. Hopefully I will have produced something functional after my 3 week period.

Wednesday, 6 July 2011

Sys Admin Disaster Recovery

I have recently been tasked with creating a proposal outlining different disaster recovery options which we can offer to clients.

The more I started to think abut this the more I realised that as a fairly novice sys admin I knew very little of the problems that can occur and the disasters that can happen.

I began to research this. I read a few blogs to begin with. One of the first that I read (http://www.simple-talk.com/sysadmin/general/unteachable-disaster-recovery-techniques/) was quite interesting. It basically outlined that while best practices and knowledge of a system will help, certain aspects of avoiding disasters comes from intuition and experience.

It seems that to quote a comment on another blog, I will need to walk the minefield to gain this experience.

http://forums.theregister.co.uk/forum/2/2011/06/14/sysadmin_it_disasters/. This article outlined the top ten sys admin disasters. What was interesting was reading some of the comments. This has helped me gain a bit of understanding into what can go wrong.

While a lot of the problems were explained by onsite (data centre) hiccups (Plugs being unplugged or emergency cut off switches located next to light switches without a protective cover) a lot of the time it was people not taking care of the backup procedure correctly.

Friday, 6 May 2011

Filtering JSLint errors via JSLint4Java

JavaScript is a nice language. However, as it's parsed line-by-line at runtime by the browser, there is the chance of unnoticed syntax errors creeping into production. This has happened to us a few times, and we have decided to take preventative measures to stop this happening, using the excellent JSLint tool.

We use a continuous integration system to automate building all our projects, ensuring all our unit tests pass without introducing regressions and that every commit to our code repository triggers a re-build of the project, and thus a run of the unit tests.

However, running JSLint through the web interface for all our JS files is a pain. Enter JSLint4Java. This library wraps JSLint with a Java API and allows JSLint to programmatically be called against many JavaScript files. This can be done from the command line, or as an Ant task.

We added the JSLint4Java Ant task as a build step to some projects, only to find that JSLint complained too much about things we didn't really care about, or consider errors. For example, "Mixed spaces and tabs." - we were getting reports of over 300+ errors across all our JS files.
Unfortunately, JSLint does not provide a way to ignore this error, thus giving the impression that our JavaScript was riddled with errors....which weren't really errors.


After digging around in the JSLint4Java code, we found a place to implement error filtering in the Ant task. We can now provide a comma-separated list to the jslint Ant task, and any errors specified in the filter will simply be ignored.
As a result of this, a project in our CI system went from 350+ JS errors to 40 after filtering out the 'mixed spaces and tabs' error.

We will submit this functionality back to the author of JSLint4Java, in the hopes that it will get patched into the project officially. Currently it's only usable from the Ant task, and not through the command line, but we do not use JSLint4Java from the command line.

Wednesday, 30 March 2011

Google Postini Woes

About a year ago we set up a Google Postini account for client as a favour. The initial setup was not trivial and took longer than expected, but eventually we had it working fine.

The client's IT support company has convinced them to move to a web based hosted email solution which on the face of it sounds fine, until that is it comes to implementation.

It seems that the new provider also uses Postini for message filtering and they are not able to setup the account whilst the domain is still active within Postini. So we need to remove the domain from Google Postini - sounds simple.

However, there does not seem to be anywhere to cancel the Postini service for a domain. When you purchase the service from Postini they send you an email with a link to a CPanel for the domain, but never provide you a password for this, and the password reset mechanism does not work (disabled?).

OK, if we can't cancel the service, then we can just delete the domain from the Postini control panel. That is where the real problems start.

In order to delete the domain, you need to delete all the users associated with that domain. Unfortunately you cannot delete the user you use to login to Postini, so that does not work. I also managed to delete  the default user, pdefault@domain.com user which caused more problems later on. If you have a similar issue - don't delete this user!

After some head scratching we came up with the solution. Add another domain to Postini, that way we can keep a user with admin access, and then delete the domain. However, following our earlier attempt, we only had one user on the account, and no default user. You cannot assign this user as the default as Postini "pdefault@domain.com" for this user. Also without a default user you cannot create any more users, Postini returns the error "No default user available for organization".

I spent an hour or so trying to get the default user recreated in various different ways including hacking together some bulk upload scripts, but nothing was working. Eventually I stumbled across a post (can't remember where - sorry) stating that Postini actually only checks that the default user's email starts with "pdefault" and that you can change the email address of existing users.

From there it is plain sailing - just prefix the existing user with "pdefault_", assign it as the default user for all the organisations, create a new domain and a new default user, rename the existing user to admin@newdomain.com, and finally delete the old domain.

I sincerely hope this helps someone, as the online support is very thin on the ground and the solution not immediately obvious. Overall I am left with the impression that the Google Postini service is all a bit thrown together without anyone having thought through the various operational issues. After a year it does not seem to have improved at all, obviously not a priority for google, and we certainly won't be using it again.