jeudi 14 février 2013

My experience with iOS automated testing frameworks

On my current iOS project, the focus on quality naturally pushed me to go further in automated testing.

They run locally, on simulator, on device and in CI.

Unit tests


GHUnit: http://gabriel.github.com/gh-unit/
OCMockito: https://github.com/jonreid/OCMockito
OCHamcrest: https://github.com/hamcrest/OCHamcrest

Pros


  • GHUnit support for asynchronous operations
  • Ease of use of OCMockito and OCHamcrest

Cons

?

KIF

https://github.com/square/KIF

Pros


  • Run fast and consistently
  • Easy access to the application objects since the tests are written in Objective C
  • Extensible

Cons


  • Tests language is not QA/Client friendly

Extension for long tap / press

As a new method of UIView+KIFAdditions (thanks to: http://blog.dimaj.net/content/howto-long-press-kif ) :

- (void)longTapAtPoint:(CGPoint)point withDelay:(NSInteger)delay andCompletion:(void(^)(void)) completion
{
    // Handle touches in the normal way for other views
    UITouch *touch = [[UITouch alloc] initAtPoint:point inView:self];
    [touch setPhase:UITouchPhaseBegan];
    
    // Create the touch event and send it to the application
    UIEvent *event = [self _eventWithTouch:touch];
    [[UIApplication sharedApplication] sendEvent:event];
    
    // Perform long touch
    dispatch_after( dispatch_time( DISPATCH_TIME_NOW, NSEC_PER_SEC * delay), dispatch_get_current_queue(), ^(void){
        [touch setPhase:UITouchPhaseEnded];
        [[UIApplication sharedApplication] sendEvent:event];
        
        // Dispatching the event doesn't actually update the first responder, so fake it
        if ([touch.view isDescendantOfView:self] && [self canBecomeFirstResponder]) {
            [self becomeFirstResponder];
        }
        
        if (completion) completion();
    });
    
    // Release the touch
    [touch release];
}

Calaba.sh

http://calaba.sh

Pros


  • Tests in Gherkin langage, BDD Cucumber
  • Powerful CSS like selectors
  • Gesture recording and playback : you can record complex gesture
  • iOS and Android support

Cons



  • Issues with the execution of tests where the interaction with the UI stopped working, did not find why (Button tap not working in some scenarios only)
  • Execution of test action not very reliable: gestures stop working, maybe issues with the embedded calaba.sh server.


lundi 10 décembre 2012

Embedding a Core Data model from a static library project

In one of my project, I want to share a Core Data model between 2 projects. I have a common static library project where the model and classes are defined.

Situation


  • a common project that builds a static library which contains my Core Data model (to be shared with an iOS and an OSX project)
  • my main iOS project

Problem

  • static library cannot include resources
  • how can I give make my main project use the Core Data model ?

Solution

  • Create a new target of type Bundle (in OSX/Frameworks and Library)
  • Change the build settings of this target:
    • Base SDK:  Latest iOS 
    • Supported platform: iOS
    • Valid architecture: arm architecture
  • Add your model file (.xcdatamodeld) to the Build phases / Compile Sources section of the bundle target
  • Link your bundle with Core Data (add it to Build phase / Link Binary section)
  • Build the bundle target
Now in your main project:
  • Select the project to show Build Phases / Copy Bundle Resources
  • Drag the Bundle target product (from Products group in the project navigator) to the Copy Bundle Resources section
  • If it s not already there, add your static library: in Build Phases / Link binary section, use the "+" button to add your static library file
  • Load the model from the bundle:
NSString *staticLibraryBundlePath = [[NSBundle mainBundle] pathForResource:@"ModelBundle" ofType:@"bundle"];

NSURL *staticLibraryMOMURL = [[NSBundle bundleWithPath:staticLibraryBundlePath] URLForResource:@"MyDataModel" withExtension:@"momd"];

model = [[NSManagedObjectModel alloc] initWithContentsOfURL:staticLibraryMOMURL];

mercredi 4 janvier 2012

Mobile Application Testing

iOS

For iOS, I use the excellent KIF from Square inc. : https://github.com/square/KIF

Although it uses private APIs, it is still very valuable and run fast. It can also run headless on the simulator (think CI server)

Android

Here Robolectric from Pivotal Labs is your friend : https://github.com/pivotal/robolectric

This framework is great because it does not run on the Dalvik VM but as a regular JUnit test suite, that means speed, speed and easy integration in CI.

vendredi 29 juillet 2011

REST API Testing with Cucumber

To test an API we are working on, I wanted to document/test the API so that client developers would be able to use theses specification to learn how to use the API and the same documentation would be used to test our API.

After some research, I settled (for now) to use Cucumber, json_spec and cucumber-api-steps.

These allow me to write this kind of test against the API:

Feature: User API
Background:
Given the following users exist:
| id | name | password | email |
| 1 | ben | abcdef | ben@email.com |
| 2 | jon | bcdefg | jon@email.com |
When I sign in as "ben@email.com/abcdef"
And I send and accept JSON

Scenario: GET /users
When I send a GET request for "/users"
Then the response status should be "200"
And the JSON should be:
"""
[
{
"email": "ben@email.com",
"name": "ben"
},
{
"email": "jon@email.com",
"name": "jon"
}
]
"""
And the JSON at "0/name" should be "ben"

Scenario: GET users/1
When I send a GET request for "/users/1"
Then the response status should be "200"
And the JSON should be:
"""
{
"email": "ben@email.com",
"name": "ben"
}
"""
And the JSON at "name" should be "ben"

vendredi 8 juillet 2011

Sproutcore 2.0, Templates and Datastore

With Sproutcore 2.0, there are different ways to use the template views :

- Define a view template in the header of a page, define its View class and instantiate it from the body of the page

- Define a template in the body of the page and have it refer to its View class

Template in the <head> of the page

In the HTML:
<head>

<script type="text/html" data-template-name="account">
MODE:{{mode}}
<h1>{{username}}</h1>
<h1>{{city}}</h1>
</script>
</head>

<body>
<script type="text/html" data-view="App.MyView">
<h1>Hello world! {{title}}</h1>
</script>
<script type="text/html">
{{view App.AccountView}}
</script>

</body>

In the javascript:

App.AccountView = SC.View.extend({
templateName: 'account',
usernameBinding: 'App.accountController.content.username',
cityBinding: 'App.accountController.content.city',
mode: 'DEV'
});

Template in the <body> of the page


In the HTML:

<body>
<script type="text/html" data-view="App.MyView">
<h1>Hello world! {{title}}</h1>
</script>

In the javascript:


App.MyView = SC.View.extend({
mouseDown: function() {
window.alert("hello world!");
},
title: 'HELLO',
});

Adding the datastore


TBD


Source code
app.js

var App = SC.Application.create({
store: SC.Store.create().from(SC.Record.fixtures)
});

App.MyView = SC.View.extend({
mouseDown: function() {
window.alert("hello world!");
},
title: 'HELLO',
});

App.Account = SC.Record.extend({
username: SC.Record.attr(String),
city: SC.Record.attr(String)
});

App.Account.FIXTURES = [ { username: 'bilou', city: 'new york' } ]

App.accountController = SC.Object.create({
content: SC.Object.create({ username: 'TEST', city: 'San Francisco' }),
city: 'SF'
});

App.AccountView = SC.View.extend({
templateName: 'account',
usernameBinding: 'App.accountController.content.username',
cityBinding: 'App.accountController.content.city',
mode: 'DEV'
});

SC.$(document).ready(function(){
var account = App.store.find(App.Account);
App.accountController.content = account.objectAt(0);
});




mercredi 1 décembre 2010

Mastery Autonomy Purpose - 1

These three pillars of motivation as defined by D. Pink seem to be a perfect canvas for evaluating one's motivation status.

Let's apply it to my previous jobs:

Mastery
  • HTTP, REST API, Restlet framework (+ implemented security customizations)
  • Spring, JMS
  • OAuth, Web security
  • AndroMDA : model driven application and code generation UML -> DB-Java-Hibernate
  • Flex / Actionscript : implemented a video player and composable widgets, integration with browser plugin
  • Messaging : ActiveMQ, RabbitMQ
  • Cloud computing: Amazon Web Services, Rightscale, Engine yard
  • Javascript client side: ajax, jQuery
  • Video : playback using streaming, pseudo-streaming, download / Wowza Media Server
  • Ruby on Rails : proof of concept projects, selection and integration of all plugins needed to cover our needs
Autonomy
  • Agile methodology : the team is at the core and drives the project, user stories, sprint
  • Scrum : everyone involved/committed as a team (product, qa, dev), daily standup
  • Collective design of architecture and technical challenges
  • Collaborative management of issues, removal of blockers, celebration
  • Involved in the hiring process when building the team
Purpose
  • Technically innovative and challenging
  • Video is fun
  • Engineering was core to the business
  • Excellent team, common goal and investment

vendredi 13 août 2010

Personal Kanban and Pomodoro technique

For a few weeks now, I've been using both a personal Kanban board and the Pomodoro technique.
I've been using the Pomodoro technique for a little while now and I really appreciate the gains in term of productivity and focus.
The satisfaction of getting the things done more efficiently feels great. The breaks are fully appreciated: they allow me to rest my shoulders and back as well as to deal with the 'noise' : emails, twitter, etc.

The personal kanban board helps me and my coworkers to visualize what I'm working on. I limit my work in progress and see at any moment what I've accomplished, what's left for the current timeframe.

I invite you to try these tools to enhance your day to day work and feel.