Wednesday 15 January 2014

Functional Testing Starling Applications with Cucumber and Melomel Redux - Part 2

Command Line Building

In my last post (http://ttmmhe.blogspot.co.uk/2014/01/functional-testing-starling.html) I discussed the pains of not taking a test first approach to building applications.  One of the core pieces to be successful in feature based development is to be able to consistently build and test your application, this means being able to build it almost anywhere and run your tests without the need for a developer to run the build an army of testers to manually click through it.

The first step to this is to get a build script running which could be executed on by your continuous integration server.

Thankfully there are a number of handy tools out there which you can use to create your build scripts, Ant, Maven, Gradle, Bash, Rake to name but a few, my personal preference is Rake which is ruby based, mainly as it integrates well with lots of other Ruby packages which use for testing and also its quite simple to write.

For this example I am going to use Rake and the Ruby gem ASRake which handles all our compiler commands very nicely.  It is not the purpose of this tutorial to go into the depths of Rake, the internet has many far better than I could write.

We are going to compile the demo which comes with the Starling download, other than changing a few file paths I have not modified the code at all.  All source for this example can be found at:

https://github.com/nicholasjackson/melomel_starling_example

The context of this assumes that you are using a mac or linux environment if you are using windows you will need to change the paths from / to \ however everything should still work.

Flex SDK

You are going to need a Flex SDK, I am currently using the Apache SDK 4.11 you can download this from http://flex.apache.org/ this will also install the Air SDK if you select it as an option.

ASRake requires that you set the environment variable for FLEX_HOME you can set this by executing the terminal command:
"export FLEX_HOME=/path/to/your/sdk"

Rakefile

For our build we have a few dependancies:
Ruby
ruby gem :- asrake
ruby gem :- zip

My personal preference is to use RVM (http://rvm.io/) to manage my Ruby installs and gemsets, the two files .ruby-gemset and .ruby-version let RVM know which gemset repository and version of ruby you would like to use.  Think of gemsets like workspaces, you can install all sorts of gems but they are local to that gem set so if you are working on a different project which has different dependancies there is no conflict.

There is also a file called Gemfile the contents of this are....

source 'https://rubygems.org' 

gem "cucumber", "~> 0.10.0"
gem "asrake", "~> 0.14.1"
gem "zip", "~> 2.0.2"
gem "rspec", "~> 2.14.1"

This file is used by the Ruby bundler command which will download and install the gems from the repository rubygems.org and install them for use in your gemset.  Currently we only need asrake and zip for this part of the process but it will not hurt to install the others.

From your command line execute 
"bundle"

If your system complains you do not have bundler then you may have to install it with "gem install bundler".

Now lets look at our Rakefile, at the top of the file we are defining our ASRake setup:

args = ASRake::Mxmlc.new "bin/Demo_Mobile.swf"
args.file_specs = 'src/Demo_Mobile.as'
args.target_player = 11.9
args.debug = true
args.source_path << "src"
args.library_path << "libs"
#args.external_library_path << "air/nativelibs/NativeGATracker-v2.0.4.ane"
#args.external_library_path << "air/nativelibs/NativeExtension.ane"
args.isAIR = true

current = Dir.pwd
unzipDir = "#{current}/unzippedane"

I'm going to run through this line by line but this is going to do our build.

# Create a new instance of as rake and specify the output directory for our compile binary, in this case the bin folder and Demo_Mobile.swf as a filename.
args = ASRake::Mxmlc.new "bin/Demo_Mobile.swf" 

# This line defines the path to our applications main class.
args.file_specs = 'src/Demo_Mobile.as'

# The version of player you wish to target.
args.target_player = 11.9

# Set to true to enable debug mode, false for your release builds.
args.debug = true

# Set your source path, if you have multiple source paths you can just add this line multiple times with your difference source paths.
args.source_path << "src"

# Set your library paths if you are using any pre-compiled libraries, again this can be set multiple times if you have more than one library path.
args.library_path << "libs"

# This line is commented out for our example as we are not using any native extensions however if you are then you add them like so.
#args.external_library_path << "air/nativelibs/NativeGATracker-v2.0.4.ane"

# We tell the compiler we are going to build an adobe air app
args.isAIR = true

# Set a variable to the current working directory
current = Dir.pwd

# Specify the directory to which we would unzip any ANE files should we have any
unzipDir = "#{current}/unzippedane"

Full details about the package can be found on the Github read me: (https://github.com/nexussays/ASRake)

Build Task

task :build => [args,:unzipane] do 
cp_u "src/Demo_Mobile-app.xml", "bin/"
Dir.glob("assets/*") do |folder|
cp_r folder, "bin/"
end
end

In the definition of this task the => arrow signifies that the task has a dependancy on other tasks, in this case args which is our ASRake build and unzipane which would unzip any native extension so that they can be picked up by the debugger.

By simply making a dependancy on the ASRake builder Rake will automatically invoke the execute method of args, sometimes you may only want to build your application and therefore your task would be nice an neat however in this instance we need to copy some assets which are loaded at runtime by the app.

I am not going to examine the :unzipane task as we are not using it in this example, its just there for reference should you need this.  If I get the time I will fork ASRake and add unzipping native extensions and running the build as rake tasks removing all this ugly code.

Build Our Code

This is the complex part, actually its not really all you have to do is type 
"rake build"

Hopefully you do not have an error message and you are now good to run the application.

Run the Application

I have created a rake task called run to start the Air Debug Launcher, the full settings and help can be found here (http://help.adobe.com/en_US/air/build/WSfffb011ac560372f-6fa6d7e0128cca93d31-8000.html).

The below code executes a shell command which starts the ADL.  The ADL requires certain parameters such as profile (mobile, desktop), screensize (predefined such as iPhone or custom), platform and a path to your application config xml file.  This file contains details such as the swf to start and various settings for the runtime.  Its exactly the same code that IntelliJ or Flash builder would generate for you.

flex = ENV["FLEX_HOME"]
sh "#{flex}/bin/adl -extdir #{unzipDir} -profile extendedMobileDevice -screensize iPhone -XversionPlatform IOS #{current}/bin/Demo_Mobile-app.xml"

To run the app all we have to do is execute the task run like so:
"rake run"

In our rake file you can see that run has a dependancy of build so all the build tasks would be executed before the ADL is started, this is mainly because I generally change code and forget to build then spend ages working out why my bug is still there.  If you just want run to run then remove => :build.

Hopefully now you will have the Starling demo running, the next part is to look at Melomel and how we can use it for our functional testing.




Source Download



1 comment: