Using Unit Tests to Learn a Framework

I’m an increasingly big fan if unit/functional testing. While not necessarily using TDD I am aiming for comprehensive code coverage in close proximity to writing any bit of code.

With that on mind I have been implementing the Laravel PHP framework in my latest project. Laravel has great testing built in, greatly encouraging its use. (I realize that in a purist sense what I’m doing here is really functional testing as opposed to unit testing).

Rather than pour over tons of documentation I have been pleased with how much I’m learning about Laravel through the use of tests. Specifically I have been writing some custom authentication filters and routes to be used as an API for mobile apps. I have learned as much about Laravel from watching my tests fail as I have from the docs.

For example, consider this code:

Auth::login($apiToken->user());

I am first retrieving a valid API token from the http header. My ApiToken model has a belongsTo relationship with the User model. Laravel makes this relationship easy to retrieve by simply querying my API token and then getting the related User to pass to the login method of the Auth facade.

That all looks well and good except it was failing my auth tests for logging in via a token. The exception was telling me:

ErrorException: Argument 1 passed to Illuminate\Auth\Guard::login() must implement interface Illuminate\Auth\UserInterface, instance of Illuminate\Database\Eloquent\Relations\BelongsTo given

Laravel is complaining that I’m not passing a valid User model to the Auth::login() method. After fiddling with the tests and routes code I realized my mistake: The () after the ->user relationship. Even though belongsTo relationships are defined as a function like:

public function user()
{
    return $this->belongsTo('User');
}

The reality is that the relationship is called like a property: $apiToken->user instead of as a function: $apiToken->user(). Calling the property returns a proper related model where calling it as a function returns a BelongsTo object.

So functional testing showed me my coding error early on rather than trying to debug from an http client and also taught me about using the belongsTo relationship. Yes, the Eloquent docs do show the usage without the parenthesis, but I missed the distinction on my reading of the documentation.

As I wire up more and more functional tests to exercise my models, controllers and routes I get the double blessing of learning the framework more intimately and building a nice suite of tests for the future lifespan of this product.

Just in case anyone wants it, here is the AuthTest functional test I’m presently using to exercise my authentication by API token:

public function test_auth_token_with_expiration_event_index_access()
{
    Route::enableFilters();
    // Make sure we start logged out since other tests might have us in a logged in state
    Auth::logout();
    // Create temporary token to test against
    ApiToken::where('token', '=', 'abcd1234')->delete();
    $token = ApiToken::create([
        'token' => 'abcd1234',
        'user_id' => 1,
        'expiration' => date('Y-m-d', strtotime('+1 week')),
        'app_id' => 1
    ]);
    $response = $this->call('GET', '/event', array(), array(), array(
        'HTTP_X-AUTH-TOKEN' => 'abcd1234'
    ));
    $this->assertGreaterThan(0, Auth::id());
    $this->assertResponseStatus(200);
}

TDD (test driven design) Does Not Replace QA

For some odd reason it appears that some proponents of TDD think there is no longer a need for a decent QA team. Indeed, some of the biggest names in the tech world today (think Facebook or BaseCamp) didn’t have QA teams for several years.

TDD is a great concept insofar as it goes. Unit testing provides a great way to document what discrete portions of your code should do and gives a way to ensure they keep behaving as expected during refactoring.

What TDD does NOT do is validate that a given program behaves like the end user expects. That’s what Integration Testing and QA are for.

I can certainly remember QA experiences that were adversarial where the QA and development teams seemed to be in an “us vs them” battle, but my general experience has proven otherwise. Most QA teams I’ve worked with, especially those teams highly connected to the end user’s experience and needs provide an irreplaceable feedback loop between the end user and the development team.

Please do NOT take code to production that hasn’t been thoroughly QA’d. Oh, what about that urgent bug fix that the customer HAS to have in their hands tomorrow? Let’s just push that into production as soon as it is fixed, right? Wrong. If your QA team doesn’t have time to look at it then the user can’t have it. Seriously.

MKNetworkKit for iOS Network caching

Recently I’ve been working with several apps from the same client that all rely on regular posts to their web server to post various data objects from their app. Under a minimal load these network operations work properly where the app sends a data post and waits for a response back.

Just recently the app was put under less than minimal conditions however and the app came to a halt. Due to circumstances beyond their control the wifi and cell network they were using at an event with over 3000 users began to cripple. Since their app relied on immediate responses from the server the app got stuck waiting sometimes minutes for a response that usually took milliseconds.

Our solution was twofold:

First we created a local in-app cache of the data the app needed from the server. Even though the server data is regularly updated it was a good enough compromise in their setting to update the local copy on an hourly basis.

Second we implanted the freezable operation concept from MKNetworkKit. Even though we had a local copy of the data we still needed to send the user actions to the server for processing. So our lookups happen locally but the server still needed to know the action taken with the data.

With freezable operations we could immediately process the action locally and queue the operation without needing a server response. If the network is operational the post to the server happens quickly although decoupled from the lookup now. That alone sped up the app. But the real improvement came with the freezable operation during an offline situation. We queued the operation as usual and just kept on going with more local data actions. Whenever the network comes back online the frozen operations are automatically processed by MKNetworkKit. The server gets the action data and all is well but with. I performance degradation.

Definitely a vast improvement to the app

The screen utility is your friend! – aka upgrading ssh remotely

This is an “oldie but a goodie” for some of you, but it always bears a reminder.

If you try to upgrade your ssh server remotely it will likely hang when you go to restart the service after upgrading.

A client recently needed chroot sftp capabilities on their server and their OpenSSH server was out of date. They were on version 4.3 and the chroot sftp capabilities were added in 4.4. I upgraded e machine to version 5.8 today. It has been a while since I’ve needed to do this remotely and I almost restarted sshd in my ssh session when I remembered I would likely have my session disconnect during the restart and the start process would fail.

Definitely not what you want for your customer!

In comes in the wonderful screen utility. The screen program lets you start a terminal session within your session that won’t get killed when sshd restarts. I just installed screen, typed screen and entered my new session-within-a-session. Now I restarted openssh and it killed my remote session, the screen session survived and completed the openssh restart.

I was able to connect right back in to the new version of the sshd server with no issues.

Not So Fast! Adobe Flex Still Alive?

I haven’t touched Flex projects in a couple of years now. Once the iPad came out all my Flex clients dropped Adobe Flash. We moved lots of code to HTML5 in the past several years.

For all that HTML5 has to offer, however, I have often missed some of the beauty found in the Flex environment. So recently when a new client asked me to take on some legacy Flex code for updates I began digging back into Flex.

To my surprise I find myself as happy as ever to code in ActionScript and Flex. I am also quite pleased to find how well the latest AIR platform supports iOS. It may just happen that my next iOS app will be written in Flex instead of in Objective-C or in HTML5 with PhoneGap.

Sounds fun!

Vagrant Disk Trashed When Upgrading VirtualBox Too Far

User beware… If you upgrade your VirtualBox too far ahead of the guest additions installed in Vagrant then you can end up with an instability that will trash your disks in the vagrant box and cause the file system to go read only.

I kept having readonly filesystem problems and they were getting more and more frequent. After combing the vagrant and virtualbox forums I saw some hints that it might be related to Guest Additions being too far out of date with the main VirtualBox version. After following the instructions here to get my guest additions up to date I’ve had no further trouble with a readonly file system.

Automator Workflow to Reduce Large PDF Files

When I worked in the Linux world I used a variety of command line tools to help reduce the size of large PDF files. In the Mac OSX world I started looking at converting some of my same scripts over to run on OS X. There were several tools I needed to install via MacPorts and as I started that process I realized there was probably a simpler way already built into OS X. Sure enough, there is: Automator.

To all you long time Apple users Automator is old news, but it was new to me. Here is how I created an Automator workflow (and then app) to reduce PDF large files down to size by shrinking the images inside the PDF.

Open Automator and choose to create a new application.
From the Library choose PDFs.
Drag the item labeled “Apply Quartz Filter to PDF Documents” to the workflow area.

I could choose the filter called “Reduce File Size” but I want to make some adjustments to it and the default filter is locked so click the Advanced options and from the list option-click (or two finger tap) the Reduce File Size filter and choose Duplicate.

Now spin down your copy of the filter and adjust the Image Sampling and Image Compression settings. For sampling I used 50% scale, 1024 max pixels, 128 min pixels and High quality. For compression I used JPEG mode and set the quality a few notches below Max.

Now in the filter dropdown at the top choose your Reduce File Size Copy filter.

I want the PDF to be opened after reduction so go to your library and choose Files and Folders and drag over the Open Finder Items action.

Make sure Open with is set to “Default Application”.

Now save your workflow and put your compiled app on your desktop or somewhere handy. Any time you need to reduce a PDF drop it on the app icon and your PDF will be reduced and opened in Preview.

PhoneGap + ChildBrowser – Opening all non-app links in ChildBrowser

I’ve been working on a PhoneGap project with iPad as the target. Most of the app runs from an external site so after presenting local files to handle the login form and authentication the main webview then shifts to an external site where the rest of the code runs.

We are using ChildBrowser to handle showing images and PDF files from the external site so that we can don’t have to include a navigation bar in our app. The ChildBrowser plugin helps us view those files without getting locked out of the original app. That’s just the background. Now we have a new problem. Many pages in this app link to external sites that are not part of the main application. We needed ChildBrowser to handle all non-app site requests automatically so that external sites would open in the popup and not replace the view in the main UIWebView of PhoneGap. Here is how we solved it:

We started with the PhoneGap.plist preferences file. In the ExternalHosts array within that plist we added all the possible host combinations that our app considers as local to the app. This app has about seven url host variants that could be used within the app so all of those should open in the main WebView. Any host not listed in ExternalHosts should open in the ChildBrowser. Keep in mind that to allow all external sites to open we still had to put * as an entry in ExternalHosts but this doesn’t affect the logic below.

In AppDelegate.m didFinishLaunchingWithOptions method I added this logic to load the PhoneGap.plist into a Dictionary and read the ExternalHosts into an array. If anyone can tell me this is already loaded somewhere and I could have skipped this step let me know in the comments:

NSDictionary *phoneGapPrefs = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"PhoneGap" ofType:@"plist"]];
self.internalUrls = [[NSArray alloc] initWithArray:[phoneGapPrefs objectForKey:@"ExternalHosts"]];

I’m assuming you know how to create the internalUrls variable as an instance variable in AppDelegate.h. Now I have an array of all my internal host names so that any requests that don’t match that are loaded in ChildBrowser. Now we proceed down to the shouldStartLoadWithRequest method where I add this logic to check if we’re loading an external site (starts with http) and check if that site is part of our internalUrls array.


if ([[url scheme] isEqualToString:@"http"] || [[url scheme] isEqualToString:@"https"]) {
    //This code will open any url that is not in the PhoneGap whitelist in Child Browser
    if (![m3Urls containsObject:[url host]])
    {
        [theWebView sizeToFit];
        ChildBrowserViewController* childBrowser = [ [ ChildBrowserViewController alloc ] initWithScale:FALSE ];
        childBrowser.modalPresentationStyle = UIModalPresentationFormSheet;
        childBrowser.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;   
        [super.viewController presentModalViewController:childBrowser animated:YES ];   
        NSString* urlString=[NSString stringWithFormat:@"%@",[url absoluteString]]; 
        [childBrowser loadURL:urlString];
        [childBrowser release];
        return NO;      
    }
    return YES;
}

Now all urls that start with http or https as the scheme and are not in the ExternalHosts I’ve listed are considered external to our app and are loaded in ChildBrowser. At this point you might tell me that since I’m listing * as a valid ExternalHost I don’t need to list all the site-specific urls and you’d be correct as far as avoiding the whitelist. During initial development I didn’t even anticipate opening non-site urls so all I wanted to list were the site-specific urls for this app. Later on I added the * for allowing any url, but realize that listing all my internal app urls provided an easy way to accomplish my need to determine which urls were for my app and which were references to non-app sites.

Find parent form in jQuery

Needed to find the parent form of a form element. This answer on StackOverflow gave me the right answer.

Problem with jQuery-UI Draggable and Form fields – Solved!

I’ve been using the Draggable functionality of jQuery-UI on a project and ran into a new problem. I needed to add form fields like SELECT and INPUT in my draggable div. Unfortunately, since my container itself is draggable it prevents clicking anything inside the container from being selected so I can’t choose items from the dropdown or focus on the input box to type text.

The solution is rather simple. Just add the appropriate selectors in the cancel option of Draggable. Actually, in my case I’ve migrated to Sortable so I added it there. Now my cancel option looks like: “select, input”. Works like a champ!