Category Archives: Uncategorized

KYCKing My Career in the Pants

Ruprict.net has been dormant for months now, mostly because I’ve started to shift my career into a much more Ruby-colored light. In the last few months, besides really focusing all my spare nerd time on Ruby, I became the Managing Editor of Rubysource.com. As a result, all my technical blogging has funneled into that site. It is a ton of fun and the more I submerge into Ruby and its community, the more I enjoy it.

For this reason and others, I started looking for a job a few months back as well. The job search was almost exclusively Ruby jobs, which was a risk since I’ve never done Ruby professionally. However, I did land a couple of offers, which weren’t right for various reasons. This proved that I could get a job in Ruby land, something I was unsure of when I began the search.

Some weeks back, I met a guy named Les Porter at a local Ruby development meetup. Les had pasted a sign on his shirt that said he was looking for Charlotte-based Rubyists for a startup called KYCK. KYCK is “the global soccer conversation”, focusing on the social, rich media, and e-commerce aspects around the world’s most popular sport. I talked to Les a couple of times, just to see what he was offering, and we made an appointment for me to come down and see their facility.

Being honest, I did not really think the KYCK thing would pan out for me. I have never been in the startup life, always playing it “safe” with somewhat established companies. The more I talked to Les, however, the more excited I became.

KYCK offers me a change to help lead a team and build something from the ground up. It offers me a chance to focus on the technologies I love and really grow all of my skills. There will be major sacrifices in the short term, for sure. The more I thought about the potential upside, the more I realized I had to take the risk. It’s time to put my money where my mouth is and really do something. As you might have guessed, I took the job.

I start in the new year, and I am excited and terrified and anxious and a million other things. Right now, every minute of every day I am thinking about how great it could be and how much I have to learn. I think if I wasn’t scared, then I’d be pursuing the wrong path.

So, I’ll be stepping out of the ESRI world for a bit. I do love this community, so I part with the proverbial “sweet sorrow”. It has been one of the privileges of my career to watch the community around GIS and ESRI grow, while considering myself a very small part of that.

KYCK goes to public beta on January 15th, 2012. Stop by and see the site in your spare time, and if you are a soccer-head, keep KYCK on your radar and register when you can.

I wish the GIS/ESRI community nothing but success, knowing it will continue to thrive in amazing ways. I hope the community wishes me luck, as well. It is going to be a crazy ride.

Advertisements

Continuous Integration with Flex, Hudson, and ArcGIS Server, Part 3

(Part 1Part 2Part 4)

One of the tenets of continuous integration is automated testing.  The most basic form of testing, in this context, is unit testing, where each class or method is tested without running the other bits of the application.  Unit testing is focused and, hopefully, simple.  In this post, I am going to add unit testing to our application and get ant to run the tests.  There are several unit testing frameworks out there, and we’re going to use Fluint. Fluint and FlexUnit have kinda merged into FlexUnit4, which is in alpha.  FlexUnit4 is, howyousay, super-fantastic, but it doesn’t currently offer any ant tasks.  When it does, I’ll be moving to it post haste.

Go get Fluint from here.  Put the fluint-1.1.1.swc file in the libs folder of your project.  We are now ready to start with some simple Test Driven Development.  Let’s add a button that zooms the map one level in, shall we?  As all examples, it’s contrived, but the point is to focus on the process.   The process here will follow simple TDD: write a test, watch it fail, write the code to make it pass.  In order to be able to watch the test fail, we’re need a bit of a foundation.  For the sake of this article, I have made a “tests” folder in the src directory where I will store the test bits.  Also, we will need a test runner for when we want to manually run our test suite.  That can be downloaded from here and copied to the src directory as well.  Once the runner (FlexTestRunner.mxml) is in the src dir, be sure to go into the project properties and add it to the list of Flex Applications for the project.  if you’ve done all that properly, then you will be able to run the FlexTestRunner application, which runs the Fluint test suites, by default.

image

We don’t want to run the framework tests, so remove all mentions of FrameworkSuite from the code in FlexTestRunner.mxml.  In Fluint, a test runner runs test suites and test suites are composed of test cases.  We will make our own test suite, called ZoomButtonTestSuite, and our own test case called (you guessed it) ZoomButtonTestCase.  These live in the aforementioned “tests” dir.

The test suite is simple:

package tests
{
    import net.digitalprimates.fluint.tests.TestSuite;
    public class ZoomButtonTestSuite extends TestSuite
    {
        public function ZoomButtonTestSuite()
        {
            addTestCase(new ZoomButtonTestCase());
        }

    }
}

All we do is pull in our test case, which looks like:

package tests
{
    import net.digitalprimates.fluint.tests.TestCase;

    public class ZoomButtonTestCase extends TestCase
    {
        public function ZoomButtonTestCase()
        {
            super();
        }
    }
}

Before we go on, go back to FlexTestRunner.mxml and add ZoomButtonTestSuite to the suiteArray in startTestProcess, so it looks like:

protected function startTestProcess( event:Event ) : void
{
    var suiteArray:Array = new Array();
    suiteArray.push( new ZoomButtonTestSuite() );

    testRunner.startTests( suiteArray );
}

We should be ready to right our first test.  For the ZoomButton, here are the specs:

  • When the user clicks the button, zoom the map in one level.

Pretty complicated, eh?  Here’s the test:

public function testZoomIn():void{
    var button:ZoomButton = new ZoomButton();
    var beforeLevel:uint= button.map.level;
    button.doZoom();

    assertTrue(button.map.level < beforeLevel);
}

I have started with the button API design, which is the real aim of our test.  Just from this test, you can see that:

  • The button is it’s own class.
  • The button has a property called map.
  • The button has a method called doZoom() (it has to be public for this example…not sure i like that)
  • The doZoom() method changes the map level.

This won’t even compile, so let’s get that happening.

package widgits
{
    import com.esri.ags.Map;
    import mx.controls.Button;

    public class ZoomButton extends Button
    {
        public var map:Map;
        public function ZoomButton()
        {
            super();
        }
        public function doZoom():void{

        }
    }
}

OK.  The ZoomButton extends the Button class, has a map property (setter/getter not used for brevity) and a doZoom() method.  Launch the test runner, and you’ll see:

image

About what we’d expect.  The button.map property is null.  However, I don’t want to create a full blown ESRI map for my tests.  It will be clunky and slow and difficult.  We need to fake the map.  This is where Mocks come in.

Mocking What We Don’t (need to) Understand

Just like unit testing frameworks, there are quite a few mocking frameworks in Flex land.  For this article, I am going to use MockAS3. (You have to build from source.  Or you can leave a comment with an e-mail and I’ll send you my copy).  Mock AS3 is nice, as it lets us mock a class and not just an interface.  ESRI does not implement an interface with its controls (like Map) for reasons that I don’t know, but I wish they would.  Also, this unit test is an interaction-based test, meaning we are going to set expectation of how we expect the ZoomButton and the map to interact, then verify those expectations as part of the test.  This is what mocking is, testing interactions and expectations presuming all dependent objects do what they are supposed to do.

So, what do we expect the ZoomButton to do in the doZoom() method?  We expect it to call map.zoomIn(), right?  Our first, naive test was testing properties on the map.  While this is testing a valid post-condition, it bleeds too far into testing the ESRI Map control and not the ZoomButton.  After all, the ZoomButton does not set the map level, it just calls a method on the map. If it does that, we are happy with our ZoomButton.  Any issues outside of it are not related to the ZoomButton and its purpose.  With this in mind, our new test looks like:

public function testZoomIn():void{
        var button:ZoomButton = new ZoomButton();
        var mapMock:MapMock = new MapMock();
        mapMock.mock.method('zoomIn').once;

        button.doZoom();

        mapMock.mock.verify();
}

The new test now creates a mock object for the ZoomButton.map property and tells it to expect the “zoomIn” method to be called one time.  We then test the doZoom method, followed by asking the mock to verify that our expectation was met.  Here is the mock:

package tests.mocks
{
    import com.anywebcam.mock.Mock;
    import com.esri.ags.Map;
    public class MapMock extends Map
    {
        public var mock:Mock;
        override public function MapMock()
        {
            mock = new Mock(this);
        }

        override public function zoomIn():void{
            mock.zoomIn();
        }

    }
}

This follows the pretty-good documentation on the Mock AS3 Google Code site for mocking classes.  We only need to mock the methods on which we are setting expectations.  Build and launch the test runner again.

image

Test still fails, but we get a new error:  Verifying Mock Failed. We haven’t coded our doZoom() method yet.

public function doZoom():void{
    if (map)
        map.zoomIn();
    else
        throw new Error("Map is not set");
}

Now, running the tests gives us sweet green….

image

Test Ant, Test Ant…

Now, we need to get these tests running with ant.  Luckily, Fluint ships with ant tasks (which are not available for FlexUnit4 at the time of this writing, but they assure me they are coming)  However, the ant tasks will not use the FlexTestRunner.mxml.  They use a different test runner with is Adobe AIR based, called (you guessed it) AirTestRunner, which you can download from here.  Double clicking on the .air files will launch the AIR installer.  Just follow all the prompts and it will install the FlexAirTestRunner to C:\Program Files\FluintAIRTestRunner.  In that directory you’ll see a .EXE file as well as a .SWF file, which is the actual test runner.  Another caveat to running the Fluint tests with ant is that the AIR test runner requires the use of Flex Modules.  What this means is that you have to create one or more Flex Modules for your tests, depending on how you want to structure the tests.  Basically, each module acts like a container for TestSuites that you want to run, then add the module to the ant task.  Enough talk.   A sample test module can be downloaded from the Fluint Google Code site, here or can be easily written.  A Fluint test module implements the ITestModule interface, which has a single method: getTestSuites().  Here is ours:

<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" implements="net.digitalprimates.fluint.modules.ITestSuiteModule">
    <mx:Script>
        <![CDATA[

            public function getTestSuites() : Array
            {
                 var suiteArray : Array = new Array();
                suiteArray.push( new ZoomButtonTestSuite());
                return suiteArray;
            }
        ]]>
    </mx:Script>
</mx:Module>

Looks a lot like the FlexTestRunner.mxml, huh?  The only thing we have left to do now is add a test target to our ant script.  As some of you might have guessed, we need to add the Fluint ant tasks to our build.xml file.  The easiest (read: not necessarily RIGHT) way to do this is copy them into the c:\ant\lib directory.  You can get the JAR file with the ant tasks here.   Once they are in the ant lib directory, add the following line to your build.xml (right under the flexTasks is a good spot)

<taskdef name='fluint' classname='net.digitalprimates.ant.tasks.fluint.Fluint'  />

There, now we can use our Fluint tasks in the ant file.  Since the tests are using Flex modules, we’ll want to have a couple of targets in the build script: one that builds the module, and one that executes the test.  Heres’ the target that builds the module:

<target name="build-test-module">
     <echo>Building test module</echo>
    <mxmlc file='${srcpath.dir}/tests/ZoomButtonTestModule.mxml'  target-player="10.0.0"
        output='${deploypath.dir}/tests/ZoomButtonTestModule.swf' >
         <load-config filename='${FLEX_HOME}/frameworks/flex-config.xml' />
         <source-path path-element='${FLEX_HOME}/frameworks'/>
         <!-- source paths -->
         <compiler.source-path path-element='${srcpath.dir}'/>
        <!-- add external libraries -->
        <include-libraries file='${libs.dir}' />
    </mxmlc>
</target>

If you go to the command line and type ‘ant build-test—module’, it will build the module and copy it to our bin-debug directory. Now, we just need to tell the Fluint task to go find that module and run the test.  Here’s the target:

<target name='test'>
    <fluint
       debug='true'
       headless='true'
       failOnError='true'
       workingDir='${fluint.dir}'
       testRunner='${fluint.dir}/FluintAIRTestRunner.exe'
       outputDir='${report.dir}'>

       <fileset dir='${deploypath.dir}/tests'>
          <include name='**/*TestModule.swf'/>
       </fileset>
    </fluint>
</target>

You may have noticed the two new build variables: fluint.dir and report.dir.  The Fluint task needs to know where the FluintAirTestRunner.exe file resides, which is the former.  The latter tells fluint where to write the report of how the tests faired.   I added this to the bottom of the build.properties file:

#Fluint vars
fluint.dir = C:/Program Files (x86)/FluintAIRTestRunner
report.dir = ${basedir}/reports

Now, running ‘ant test’ at the command line will run our test and generate the test report.  It’s an XML file that looks like:

<testsuites status="true" failureCount="0" errorCount="0" testCount="1">
  <testsuite name="tests.ZoomButtonTestCase" errors="0" failures="0" tests="1" time="0.237">
    <properties/>
    <testcase name="testZoomIn" time="0.237" className="tests.ZoomButtonTestCase"/>
  </testsuite>
</testsuites>

So, our ant file is now running our tests.  We are well on our way to continuous integration with Flex.  Coming up, we’ll need to get some of the hardcoding out of the build file, look at our project directory structure, format our test reports to be more readable, and bring Hudson into the mix.  We have a lot to do.

I hope you find this useful.


Restart ArcGIS Server Object Manager Remotely

I wanted to post this because I think it’s cool and showcases the very tip of Windows Powershell. Plus, I got tired of keeping an RD session open the the GIS Server for when I wanted to restart AGS.

If you haven’t discovered Windows Powershell, you should. It is the command line Windows needs. I know very little about it, meaning:

  • You can use .NET to write ‘cmdlets’, which are scripts.
  • You can browse more than just files. For example, you can cd into the registry. I thought this was surreal.
  • You can easily access other boxes.
  • Tons more

Anyway, go download powershell (from the above link) if you don’t have it and open up a PS prompt. This assumes that you are on your dev box and AGS is on a remote server. Type:

Get-WmiObject -computer agsServerName Win32_Service -Filter "Name='ArcServerObjectManager'" | Restart-Service

Replace ‘agsServerName’ with your AGS Server name.  BOOM. Service restarts.  Oh, and it’ll work for any service on the box, just change the service name in the Filter expression.

I have been lightly using Powershell for a long time, but really need to do more with it.


The Bitter Coder Tutorials, Binsor Style IV: Switching Configs

Previous posts in the series:

In part four of his series, the Bitter Coder (Alex) shows how easy it is to switch configurations using Windsor.  Alex moves his config into a separate file and then comments out whichever configuration is not needed.  I am gonna take a different approach with Binsor, since we have the ability to use logic in the configuration.

Presuming we have 2 environments, dev and prod, and we want to deploy to both without manually switching configuration items.  (Note:  The big idea in this post is to show the logic, not the best practice.  I realize that keeping dev config info in a production file is icky.)  Anyway, let’s create a class that has a connection string, the ubiquitous configuraiton item:

public class ConfigDepot

{

public string ConnectionString{ get;set;}

}

So, we need something that is different between the development and production boxes to let us know which connect string to use.  For the purposes of this article, I am choosing the hostname.  Here is the Binsor:

machineName=System.Environment.MachineName

if machineName.ToUpper() == “DEVBOX”:

connectionString=”connStringDEV”

else:

connectionString=”connStringPROD”

component “class.conn”, ConfigDepot:

ConnectionString = connectionString

And the program….

static void Main(string[] args)

{

ConfigDepot cl = container.Resolve<ConfigDepot>();

Console.WriteLine(cl.ConnectionString);

}

When you run the program (which, um, defaults to the production conn string. Yikes!) and the name of your dev box is ‘DEVBOX’ then you’ll see “connStringDEV”.  Otherwise, you’ll see “connStringPROD”.

It’d be easy to add a slew of connection parameters here, but you should be wary of a couple of Booisms.  First, the if block is determined by the indention level.  So, everything that is indented the same amount is part of the block. (Check this out for code conventions.)  Also, the ‘if’ line and the ‘else’ line end in a colon ( : ) which is a bit odd.

Onward…next time we have Configuration Parameters.


The Bitter Coder Tutorials, Binsor Style III: Dictonaries

DictionaryImage via Wikipedia

Time for Part III in the Binsorization of the Bitter Coder tutorials.  The original tutorial is here.

The original tutorial created a class to handle word substitution, which looked a lot like:

public class AliasService

{

private Dictionary<string, string> _aliases;

public Dictionary<string, string> Aliases

{

get { return _aliases; }

set { _aliases = value; }

}

public string Evaluate(string term)

{

if (_aliases == null) return term;

while (_aliases.ContainsKey(term))

{

term = _aliases[term];

}

return term;

}

}

And the application code:

static void Main(string[] args)

{

AliasService aliasService = container.Resolve<AliasService>();

string sentence = “a dog ate my homework”;

foreach (string word in sentence.Split(new char[] { ‘ ‘ }, StringSplitOptions.RemoveEmptyEntries))

{

Console.Write(“{0} “, aliasService.Evaluate(word));

}

}

Now the Binsor:

import System

import System.Reflection

import System.Collections.Generic

import BitterCoder.Tutorials.Binsor.Core

aliases=Dictionary [of string, string]()

aliases[‘dog’]=”duck”

aliases[‘ate’]=”broke”

aliases[‘homework’]=”code”

component “aliases.service”, AliasService:

Aliases=aliases

So, we have a bit of strange syntax to get a generic Dictionary, but then it becomes very natural to create the entries.  Also, we don’t have to worry about the type converters that Alex mentions in his tutorial.

Running the code gives us:

a duck broke my code

All good.  Up next is Switching Configurations…

Zemanta Pixie

The Great Devlicio.us Giveaway

So, I wrote an entry for The Great Devlicio.us Giveaway, and I won! My article will be posted on Friday (tomorrow) so check it out.

I won!  I won!

Thanks to the devlicio.us folks.  I am truly flattered, surprised, and happy to be getting some kickin’ prizes.

For what it’s worth, I really did make the jump to things ALT.NET while working on a new project, which I think made it much easier.  It’s hard to pick this stuff up without a real goal in mind.  For example, I’ve been trying to  become more dangerous with Ruby, but I just can’t make much of it stick b/c I have to make up my own things to write.  I think Ruby is very cool, and it’s really the only dynamic language that I’ve futzed with (someone say “F#”?) but all my “work” work is .NET, HTML, javascript, etc.

I don’t really consider myself part of the .NET elite, whoever that is.  I feel like I blue-collared my way onto the bus.  So, if you find yourself trying to make the jump and can’t get going, drop me a comment.  I can remember being there.  Actually, I am still there in many ways, which is why I am such a great candidate for continuous improvement.

Yay!

Zemanta Pixie

Great Repository/Unit of Work/ActiveRecord Series

Ryan Lanciaux has probably one of the best series on setting up the Repository and Unit-of-Work patterns with Rhino Commons, NHibernate, Castle, and Windsor. He is also using ASP.NET MVC once his repository is all set up. Check it out.