Continuous Android testing with Guard
Because it’s my bag, I’ve been spending a lot of time these days deep in Ruby code. Nevertheless, from time to time, I do find myself ensconced in Java via the Android platform. Jumping back and forth between various languages like Ruby, Java, and JavaScript can be a lot of fun; what’s more, doing so broadens one’s view on various practices, idioms, and influences conveyed by a particular community.
Something that I found missing in Java’s community, in the form of a concrete easy to use library, is something like Ruby’s Guard. Guard is “a command line tool to easily handle events on file system modifications.” In essence, Guard makes continuous testing possible with a minimum amount of effort.
For example, with Guard, you can create a
As you can imagine, once you’ve set this up, it becomes highly addictive — why would anyone ever manually invoke Rake test again? It’s always running anyway!
Setting up Guard to invoke Ant, for example, couldn’t be any easier. You first must have Ruby installed, followed by RubyGems and Bundler. Next, in your
source :rubygems
group :development do
gem 'guard'
gem 'growl'
end
Because I’m on a Mac, I’m also using Growl, which is an OS-level notification mechanism (i.e. a popup dialog that informs you that your test suite has passed, failed, etc).
Next, you need to create a
require 'guard/guard'
module ::Guard
class Ant< ::Guard::Guard
def run_all
invoke_ant
end
def run_on_changes(paths)
invoke_ant
end
def start
invoke_ant
end
def stop
end
def invoke_ant
system 'ant clean test'
end
end
end
guard 'ant' do
watch(%r{^src/*/(.+)\.java$})
end
As you can see, this
Continuous testing in Java isn’t new. Yet, it seems that the wealth of tools and thought regarding continuous testing results in a shift towards Continuous Integration or worse, the IDE. For instance, a simple search on continuous testing tools in Java yields Infinitest and JUnit Max — both are great tools (Ben Rady, the originalInfinitest guy is one of the sharpest guys I know). These tools, however, are plugins for an IDE, like Eclipse. I abandoned Eclipse some time ago in favor of IntelliJ (and Infinitest certainly supports IntelliJ); thus, these days, I do all Android development using IntelliJ, however, I tend to rely on Ant for building Android artifacts (even though there is a Maven library for Android).
Something that I found missing in Java’s community, in the form of a concrete easy to use library, is something like Ruby’s Guard. Guard is “a command line tool to easily handle events on file system modifications.” In essence, Guard makes continuous testing possible with a minimum amount of effort.
For example, with Guard, you can create a
Guardfile
that watches your file system (naturally, you can select which types of files to watch — .rb files, etc); what’s more, when those target files change (i.e. you added some code) a trigger can be invoked, such as running a test suite, invoking a Rake command, etc. Thus, with Guard, you can set up a process that executes a test suite (or an individual test) whenever you change a source file — this alleviates you from having to manually invoke a Rake task or do something else to trigger a test run.As you can imagine, once you’ve set this up, it becomes highly addictive — why would anyone ever manually invoke Rake test again? It’s always running anyway!
Setting up Guard to invoke Ant, for example, couldn’t be any easier. You first must have Ruby installed, followed by RubyGems and Bundler. Next, in your
Gemfile
, you need to include guard as follows:source :rubygems
group :development do
gem 'guard'
gem 'growl'
end
Because I’m on a Mac, I’m also using Growl, which is an OS-level notification mechanism (i.e. a popup dialog that informs you that your test suite has passed, failed, etc).
Next, you need to create a
Guardfile
— in this case, I’m going to create an inline Guardfile
as there isn’t a plugin available (yet) to support running something like Ant. My inline Guardfile
looks like this:require 'guard/guard'
module ::Guard
class Ant< ::Guard::Guard
def run_all
invoke_ant
end
def run_on_changes(paths)
invoke_ant
end
def start
invoke_ant
end
def stop
end
def invoke_ant
system 'ant clean test'
end
end
end
guard 'ant' do
watch(%r{^src/*/(.+)\.java$})
end
As you can see, this
Guardfile
simply watches any .java
file and if any change, run’s ant clean test
— theGuard
base class is fairly straightforward — there are a series of hook methods you can implement. In this case,start
is called the first time you fire up Guard. run_on_changes
ideally is used to run a single test as you have access to the incoming file path of what’s changed; however, in this case, I’ve chosen to run the suite again as parameter passing into Ant & invoking a special JUnit task with single tests is somewhat painful (but it could be certainly done). Finally, run_all
is called at special points, such as after you fix a failing test, etc. In essence, these are lifecycle methods and you have complete control over what happens when they are invoked.Continuous testing in Java isn’t new. Yet, it seems that the wealth of tools and thought regarding continuous testing results in a shift towards Continuous Integration or worse, the IDE. For instance, a simple search on continuous testing tools in Java yields Infinitest and JUnit Max — both are great tools (Ben Rady, the originalInfinitest guy is one of the sharpest guys I know). These tools, however, are plugins for an IDE, like Eclipse. I abandoned Eclipse some time ago in favor of IntelliJ (and Infinitest certainly supports IntelliJ); thus, these days, I do all Android development using IntelliJ, however, I tend to rely on Ant for building Android artifacts (even though there is a Maven library for Android).
0 comments:
Post a Comment