<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
   <channel>
      <title>Z1R0</title>
      <link>http://www.z1r0.com/</link>
      <description>All your base are belong to us!</description>
      <language>en</language>
      <copyright>Copyright 2011</copyright>
      <lastBuildDate>Fri, 12 Aug 2011 11:24:45 -0700</lastBuildDate>
      <generator>http://www.sixapart.com/movabletype/</generator>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs> 

      
      <item>
         <title>The Big Picture : Part 4 - The Automation Environment</title>
         <description><![CDATA[<h2>Continuous Deployment</h2>

Human error is fundamental to the endeavor of creating software. Our ultimate aim to not to completely remove error (an impossible task), but to be aware when errors are introduced. This awareness is what makes for better software, not simply automation itself. There are a large classification of behaviors where the computer does not know or care which behavior is correct. Being able to use relative judgement is still a characteristically human trait.

Automation is the 80/20 solution (give or take a few percent). It should cover a majority of the test cases, but depending on the complexity of the application, automation does not generally encompass all possible tests. What it does is remove the tedium from tests which are amenable to automation. This allows manual tests (which should still be done) to focus on the really hard 20 percent where no amount of automation (barring artificial intelligence) is sufficient to determine the correctness of behavior.

There are few key components to creating the automation environment - Continuous Integration, Virtualization, and Scripting. Each is discussed in detail.

<h2><a href="http://jenkins-ci.org/">Jenkins/Hudson</a></h2>

<a href="http://martinfowler.com/articles/continuousIntegration.html"><b>Continuous Integration</b></a> is the cornerstone of any automation effort. If you have not integrated CI into your development practices, stop and invest the time to do so. Without CI, you do not have a means of coordinating the efforts of the entire organization to improve the quality of the produced software. 

The original focus of CI was on developers. By generalizing this principle to the entire application stack, we move towards Continuous Deployment. Not only are applications tested (via unit / integration tests for code level validation) when built, but the built artifacts themselves are deployed without user intervention to run complete end-to-end tests. This type of testing ensures that the software will work when fully integrated and deployed, not simply tested in isolation.

Automated acceptance tests should be run when either a new version of the application is available or when tests against the application have changed. Test execution is coordinated through a dependent project which is aware of either application or test project changes. I strongly suggest to separate out executing end-to-end automation from the actual acceptance test framework. Should either change, it has minimal impact on the other.

The role of Jenkins in the Automation Environment is the that of the Coordinator. Built artifacts for both the application and test clients are moved to a Staging Area in the environment. The Staging Area contains assets for the client machines (which include the target web browsers), the application servers, and the database. In addition, it can contain the scripts which coordinate actions between the various nodes of the automation environment. 

<h3>Caveat</h3>

Jenkins currently does not allow projects to reference other workspaces. In some cases (such as with the application artifacts), the copy operation may be coupled with the application project. Depending on the size of your published artifacts, this may add considerable time to the build process. Also non-build failures, such as the inability to push artifacts into the test environment result in build warnings.

<h2><a href="http://www.vmware.com/">VMWare</a></h2>

There are generally three classes of machine in a 3-tier application environment:

<ul>
<li>Clients (consisting of different target OS/Browser combinations</li>
<li>Application Servers (consisting of the supported OS/Application environments</li>
<li>Database Servers (consisting of supported back-ends)
</ul>

VMWare (as well as other virtualization platforms) enables having the entire application environment in a self-contained network. End-to-end testing can then use this environment to test against different combinations of the application stack. Tests which succeed in all combinations validate consistent behavior across the supported architectures.

The elegance of this solution is that it can easily scaled by simply adding more VMs. Hardware is typically the constraining factor in virtualization solutions which are highly dependent on memory and I/O. Modern multi-core processors are more than sufficient from the point of view of a client VM. CPU affinity and proper resource allocation can ensure that VMs are sufficiently provisioned for their role. There are few principles to follow when designing your virtual infrastructure:

<ol>
<li>Ideally, you have enough physical RAM to hold all VMs in memory without swapping.</li>
<li>Drives which have fast IOPs reduce disk contention (important for Windows VMs which like to swap)</li>
<li>CPU allocation should not exceed actual number of Cores/Threads</li>
</ol>

In addition, VMWare supports virtual snapshots.Snapshots allow for VMs to be restored consistently to a known state. This feature removes the need to physically start machines and wait for boot up. VMs are started and ready to run immediately. In addition, tests which make non-reversible changes to the database layer can have their changes undone by simply restoring the VM to its original snapshot. This ensures that tests can run against a known baseline environment. Variation between test runs is minimized, if not entirely eliminated.

Operations against VMs (such as starting and restoring snapshots) is supported by VMWare through the use of the <code><b>vmrun</b></code> utility. In addition, <code><b>vmrun</b></code> also allows commands to be executed within the guest VMs from the virtualization host. Scripted test execution from and external trigger is possible when combined with shell/Ant scripts on guest VMs. If these scripts are available on a common Staging Area as suggested in the previous section, all dependent guest VMs can use the same scripts between test executions.

In addition, <code><b>vmrun</b></code> can be used against snapshots. If testing against the same OS with slight variations, you can save space by taking snapshots of the core image with the variations applied. For example if you are testing Windows clients with various Service Packs, you can take a snapshot against each Service Pack state you wish to test against. When invoking a test, all you need to do is specify the appropriate snapshot.

<h3>Supplementary Services</h3>

Since the virtual environment is a full functional network, there are a few services which make managing VMs easier.

<h4>DNS/DHCP</h4>

Name resolution and network configuration can be unified using DHCP with dynamic DNS updates. This allows all machine IPs/names to be centralized to the <code><b>dhcpd.conf</b></code> file (assuming you are using a Unix/Linux host). The Workstation/Fusion/Server versions of VMWare natively support DNS/DHCP through their built-in virtual network interfaces for the NAT or Host-only networking configuration. In ESXi, this ability is not present as there are are no virtual network interfaces; a dedicated host for managing this service is necessary.

It is strongly recommended that you avoid using static IPs for hosts as well as providing static host mapping files. This solution quickly becomes difficult to manage as you add more machines to the system as changes to the network have to be propagated to all hosts participating in the same network.

<h4>NTP</h4>

VMs are sensitive to time differences, specially if they attempt to synchronize their clocks against the host's internal clock. To avoid time drift between VMs, it is suggested that you use NTP to synchronize all VM clocks. By removing this source for variation, you can ensure that time-sensitive operations, such as establishing secure connections, happens reliably within the virtual environment. Time drift may affect secure connections as most security mechanisms protect against replay attacks by having a sufficiently small connection windows.

<h4>HTTPS</h4>

There may be times when you are required to simulate connections over HTTPS. To ensure that invalid certificate messages do not interfere with client tests, create a self-signed certificate for the application server. Import this self-signed certificate as a root certificate authority on the client VMs. Connections should be established without security messages.

<h2><a href="http://ant.apache.org/">Ant</a></h2>

Scripts are the glue that binds the Coordinator (Jenkins in this example) to the VMs that participate in test execution. Automation scripts should be treated as code; include them with your version control system. In this example we use Ant, but certain tasks may be better served with DevOps tools such as <a href="http://wiki.opscode.com/display/chef/Home">Chef</a> / <a href="http://projects.puppetlabs.com/projects/puppet">Puppet</a>.

Ant should be structured with a number of custom targets corresponding to the various phases of test execution. To kick off test execution, the Jenkins run automation project is started which invokes an ant script at the root of the Staging Area on the VM host responsible for managing the participating guest VMs. The phases are as follows:

<h3>Pre-automation</h3>

<ol>
<li>Set the test build to use for the clients.</li>
<li>Set the app build to use for applications.</li>
<li>Execute application config pre-conditions such as setting configuration information.</li>
<li>Start the VMs in the order of their dependencies; usually the database first, followed by the application server, and lastly the client VMs being used. Ant allows for the use of the elements <code><b><sequential></b></code> and <code><b><parallel></b></code>. Generally, database and application starts occur sequentially, but client VMs can be started in parallel.</b></li>
</ol>

<h3>Test Execution</h3>

<ol>
<li>Execute tests on client VMs.</li>
<li>Collect test artifacts and results and publish them to a known location.</li>
</ol>

<h3>Post-automation</h3>

<ol>
<li>Suspend all VMs in parallel.</li>
<li>Revert the VMs to their base snapshots. This step ensures that the VMs are ready for the next test execution run</li>
</ol>

There were a number of Ant/Ant-Contrib tasks that I used to 

<ul>
<li><b><a href="http://ant-contrib.sourceforge.net/tasks/tasks/propertyregex.html">propertyregex</a></b> - Performs regular expression operations on an input string, and sets the results to a property.</li>
<li><b><a href="">timestampselector</a></b> - The TimestampSelector task takes either a nested <path> element, or a path reference, and sets either a named property, or a path instance to absolute pathnames of the files with either the N latest or earliest modification dates</li>
<li><b><a href="http://ant.apache.org/manual/Tasks/sshexec.html">sshexec</a></b> - Runs a command on a remote machine running SSH daemon.</li>
</ul>

<h2>Miscellanea</h2>

As I suggested previously, the use of single Staging Area simplifies Continuous Deployment. When testing against different supported application servers, it allows a single copy to be used for configuration purposes. Each application server variant configures itself against the same build. Keeping a recent history of published artifacts in the Staging Area also allows for test run comparisons. By resetting a symbolic link to select the current build to use, you have the ability to troubleshoot between versions of the application/test builds.

<h2>TODO : Grid and Automation in the Cloud</h2>

To fully leverage the Grid, tests need the ability to run in parallel. There are a number of strategies that can be employed to achieve this, but I'll defer to a future article on Grid usage. There are a few experiments that I'd like to try first before committing to any design. In addition, the use of Grid should be consistent whether you are running it from your own environment (as above) or in the Cloud (via SauceLabs). 

]]></description>
         <link>http://www.z1r0.com/2011/08/the_big_picture_part_4.html</link>
         <guid>http://www.z1r0.com/2011/08/the_big_picture_part_4.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Automata</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">java</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">jbehave</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">jenkins</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">programming</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">webdriver</category>
        
         <pubDate>Fri, 12 Aug 2011 11:24:45 -0700</pubDate>
      </item>
      
      <item>
         <title>The Big Picture : Part 3 - Organization is Key</title>
         <description><![CDATA[<h2>Modularity</h2>

While tests should be comprehensive, only the test automation usually is required to run the complete suite of tests; test and application developers generally work on a subset of the entire framework. This is more important when test runs become time consuming. Immediate feedback encourages the use of tests; delays in receiving test results interrupt workflow and make it less likely that will used concurrently with development. Ideally, testing can be initiated from within the IDE (Eclipse in this case) or the command line (which ever is preferable to the developer). Being able to support both modes of execution fulfills the different requirements of developers versus automation.

The design of the test execution encourages the use of java Properties; these can have local overrides which are used for development, but can be overridden when executed in the context of automation. This article focuses on scriptable execution via Ant; other build tools such as Maven can also be used.

Test configuration parameters that should be made into Properties include:

<ul>
<li><b>application URL</b></li>
<li><b>username & password</b></li>
<li><b>browser type</b></li>
</ul>

<h2>Reference Datasources</h2>

In addition to having modular tests, a reference database is essential. A reference database should provide only enough functionality to verify application behavior. This allows separating out configuration dependent tests from core functionality. By being able to differentiate between core and configuration, you have better separation of concerns. Failures in actual application behavior can be distinguished for misconfiguration errors. In addition, for test behavior to be replicable, the same test pre-conditions should be present for every test execution run. Using VMWare snapshot functionality or Oracle's FlashBack capability allows you to ensure that your database is in a consistent known state when tests are run.

<h2>Test Organization</h2>

The organizational mechanism employed depends on the tools you use for test execution. Below, I discuss the use of JUnit and JBehave mechanisms for organizing tests into workable modules. In addition to using the tool's organizational support, it is also helpful to use package namespaces to modularize the physical test files.

<h3>JUnit</h3>

JUnit has the <code><b>@RunWith(Suite.class)</b></code> and <code><b>@Suite.SuiteClasses</b></code> class annotations which allow you to create a hierarchy of suites with one master suite (used by automation) to include other functionally distinct suites. Within these functional suites, I suggest separating out Reversible and Non-Reversible tests. Reversible tests do not make permanent database changes, while NonReversible tests do. Application developers can use Reversible suite for quick smoke tests. Ideally, you will the restore the reference database to its initial state after the execution of NonReversible tests. This ensures consistency between test runs. This is even more important if you are testing outputs based on fixed/known inputs and want to compare it with an expected output.

<h3>JBehave</h3>

JBehave's organization is based on the concept of a Story. A Story is a functionally cohesive set of scenarios. Scenarios are the actual behaviors which describe the story's functionality. In addition to using Stories, it is useful to also modularize the Stories themselves along functional application lines. Step classes and story files are required to run JBehave tests. Story files are simple text specifications which include everything necessary to describe the expected behavior given a set of pre-conditions, operational steps, and expected post-conditions. Step classes are responsible for mapping the scenario language to actual test automation commands. Both Steps and Stories can be reused. I suggest keeping them in separate directories. JBehave uses reflection to determine which stores to run via the <code><b>storyPaths()</b></code> method on <code><b>JUnitStories</b></code>. This uses an Ant-like path expression to find textual stories which JBehave inspects to invoke test methods. Using more specific path expressions in the various functional specific stories limits test execution. Conversely, a single JUnitStories class with a sufficiently general path expression should be able to find all stories in your project. 

<h2>Versioning</h2>

Tests should be considered programmatic artifacts; like application code, they should be managed via a source code repository. Treating tests as code allows us to do all the normal things version control allows. Test file histories document the changes required as the application evolves. In addition, it is useful to be able to version test collections in relation to the application releases/branches. This allows for test development to proceed unhindered on development branches while supporting writing new test cases against the  stable release (with the understanding that tests applicable to the development branch will be ported).

<h2>Test Context</h2>

Inevitably, you will have to reconstruct context to understand the reasons behind why a given test was written a certain way. Files that you used to troubleshoot the problem domain must be found again and inspected to fully understand the implications of a change. When this reconstruction happens is indeterminate; it might be tomorrow or a year from now. Unfortunately, your ability to reconstruct this context diminishes over time. In addition, there is a (high) probability that the person who may need to make sense of this context may be someone other than yourself.

What is need is a mechanism to associated this context with the test. If you are using Eclipse, Mylyn's saved contexts in conjunction with the appropriate adapter for your defect system (such as Redmine/Trac/Bugzilla) solves this problem. By having the ability to associate a context with a defect (via a zipped file which contains your project layout), you remove the limitation of an individual's memory and instead leverage the automation system's abilities.

<h2>What's Next?</h2>

Now that I've established some basic principles for creating a test automation framework, I'll describe how to put it all together to support continuous deployment using Jenkins/Ant/VMWare. The goal is to provide a feedback system for application development. The sooner developers are aware of potential regressions caused by application changes, the quicker they can respond to fixing it.]]></description>
         <link>http://www.z1r0.com/2011/08/the_big_picture_part_3.html</link>
         <guid>http://www.z1r0.com/2011/08/the_big_picture_part_3.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Automata</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">java</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">jbehave</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">jenkins</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">programming</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">webdriver</category>
        
         <pubDate>Thu, 11 Aug 2011 11:24:13 -0700</pubDate>
      </item>
      
      <item>
         <title>The Big Picture : Part 2 - Testing for the Common Man</title>
         <description><![CDATA[<h3>What Are We Testing?</h3>

To be clear, the focus of this article is to discuss tests which involve various client web browsers which connect to the application. There are other kinds of tests that we will not cover here - unit tests and integration tests (at the service level). There are other tools which are suitable for those tests and they fall under the responsibility of the application developers themselves. More importantly, these types of tests are non-client facing. 

What is important however, is that tests cover the behavior of different versions and kinds of web browsers. While WebDriver supports HTMLUnit via the WebDriver interface, we focus primarily on browsers supported by the RemoteWebDriver interface. This includes the following browsers:

<ul>
<li><b>Firefox</b></li>
<li><b>Chrome</b></li>
<li><b>Internet Explorer</b></li>
<li><b>Opera</b></li>
</ul>

The only unsupported major browser is Safari. Writing tests against the RemoteWebDriver allows us to keep them browser agnostic. In addition, Grid 2 currently supports only RemoteWebDriver clients. 

Everyone seems to have a different definition of for particular kinds of tests. For the purpose of this discussion, I'd like to offer my own definitions; others however, will likely disagree with these categorizations.

<h2>Acceptance Tests</h2>

All tests which ensure that the application behaves as expected can be considered Acceptance Tests. Within this categorization are other sub-categories.

<h3>Smoke Tests</h3>

Smoke Tests ensure that the application is technically functional. Generally, these type of tests ensure navigational and Element behaviors are consistent through the application. Validation at the Element level could be done programmatically as part of these tests. Smoke Tests are capable of verifying technical requirements, but generally at the expense of providing user context to the operations. These types of tests are useful for programmers, but not so much for end users. 

<h3>Specification Tests</h3>

Specification Tests use the language of the user domain to express application behavior.   The value of using specifications is that these tests create a consistent vocabulary which is used to communicate end-user expectations to programmers. Essentially, these specifications form the foundation of acceptance criteria which is codified in a readable manner. There are many different specification frameworks, but I choose JBehave for the simple fact that specifications are written in plain text. This makes it easy for non-technical endusers to contribute to the creation of specifications. Features as well as bugs can be described via Stories and Scenarios. 

<h3>Regression Tests</h3>

Regression Tests typically express defects within the application to which fixes have been applied. The difficulty with this type of test is usually a question about with reproducibility. By using the same language used for Specification Tests, preconditions, steps to simulate the behavior, and expected outcomes are clearly expressed.

<h3>Performance Tests</h3>

Performance Tests are generally designed to exert load on the application back-end. There are tools such as JMeter which apply the record-playback principle for generating load, but tools such as this have limitations. If your application uses dynamically generated assets, these types of tests are difficult to use. In addition, it is questionable whether tests based on JMeter measure actual application behavior against a client or the ability of the application server to respond to concurrent requests.

Synthetic browser tools remove a critical part of the equation - the browser itself. While HTMLUnit can be used in this scenario as well, it is not a browser that end users are likely to use. Different browser introduce variability (such as different javascript engines) that must be accounted for. This is more important for applications that are AJAX aware.

<h2>One and the Same</h2>

Code reuse is a fundamental principle in managing complexity in large software projects. As test coverage expands to cover more aspects of the AUT, leveraging this principle becomes crucial to manage the tests themselves. 

Ideally, Specification and Regression Tests can be re-used for measuring performance. This allows for load testing using a single framework. This can be accomplished through the use of a concurrency demultiplexer that can take single Specification or Regression Tests and dynamically create multiple concurrent instances (determined at runtime) of the test to run. JUnit natively supports concurrency through the RunnerScheduler. You can effectively simulate group tests using this method. 

This solution however, requires a number of machines to run the tests. Virtualization can be used to provision client browser machines, but has it's own costs. One must balance the costs of machine resources with human resources.

<h2>Domain-specific Languages (DSL) To The Rescue</h2>

<a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">Behavior Driven Development</a> engages end-users in defining application behavior. Instead of simple technical requirements driving application development, the perspective of the enduser is given a central role. Specifications are written using the language of their domain; this provides the necessary context for considering the success or failure of a behavior. This is the role of the <a href="http://en.wikipedia.org/wiki/Domain-specific_language">Domain-specific Language</a>; <a href="http://jbehave.org/"><b>JBehave</b></a> is particularly useful in this regard.

JBehave allows the following:

<ol>
<li>Specifications can be written in plain text.</li>
<li>Specifications use a structured syntax that clearly expresses pre-conditions, steps, and expected outcomes.</li>
<li>Specification encourage stories to be written in the point-of-view of a User of an application. This allows allows for specifications to be defined for different perspectives given a User's role within an application.</li>
<li>Instead of tests expressing operations at the component (Element) level, instead they describe functionality in the context of individual user operations (Scenarios) grouped by functionality (Stories).</li>
<li>Stories are reusable a pre-conditions of other stories.</li>
<li>Parameterized steps allow for table-driven input. This effectively removes the need for tools like Fitnesse. Both input and output can be specified with the test.</li>
</ol>

<h3>Caveat Emptor</h3>

While JBehave is generally useful for BDD, it is not without its faults. My initial attempt to use the GuiceAnnotatedEmbedderRunner was a complete failure. The documentation surrounding its use and the associated documentation where insufficient to diagnose my issues. Barring a source-code evaluation of JBehave's implementation of this feature, I would recommend avoiding it. 

In addition, I would suggest avoiding the JBehave-Selenium module. There are design flaws in its implementation which tightly couple test code to WebDriver. Pages created in the manner suggested by JBehave-Selenium inherit directly from WebDriver thus breaking encapsulation. Changes in WebDriver APIs have a direct impact on the Page implementation. Using Dependency injection via an injector framework, or manually via constructor injection is the only requirement for the Page. As per the Gang of Four, favor composition over inheritance.

In addition, having a typed WebDriverProvider exposes the browser implementation details into the test framework; this should be safely abstracted away into a Configuration object.

<h2>The Grid</h2>

Grid allows tests to distributed across machines for parallel execution. This is particularly useful for load testing as well as providing concurrent testing against various browser types and versions. When combined with different operating systems, this method provides an effective means of testing an application across a number of different platforms simultaneously. A single virtual machine can have multiple grid nodes which can consist of different browser types. The number of nodes per machine only limited by memory. By having a central repository of available browser resources, scheduling concurrent test execution becomes manageable.

The structure of the automation environment plays a direct part in how Grid is used. I'll cover this in more detail in Part 4.

<h2>What's Next?</h2>

The number of tests against a mature application only increase over time. This requires a method for organizing the tests themselves. The next article deals with issues of test organization and how to introduce modularity and versioning to your tests.
]]></description>
         <link>http://www.z1r0.com/2011/08/the_big_picture_part_2.html</link>
         <guid>http://www.z1r0.com/2011/08/the_big_picture_part_2.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Automata</category>
        
          <category domain="http://www.sixapart.com/ns/types#category">SOTA</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">java</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">jbehave</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">jenkins</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">programming</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">webdriver</category>
        
         <pubDate>Wed, 10 Aug 2011 11:23:42 -0700</pubDate>
      </item>
      
      <item>
         <title>The Big Picture : Part 1 - Plan for Change</title>
         <description><![CDATA[There are a few misconceptions regarding Selenium / WebDriver that should be clarified from the start. When I first began to use Selenium (pre 1.0) the mechanism for automation relied on the technique of Proxy Injection. While this worked well for applications which rendered largely static content, the wide-spread use of AJAX made this technique very unreliable from an automation point-of-view. Timing was difficult to manage and required client-side javascript to notify automation of the application's ready state. In addition, it was impossible to account for browser events that were not represented in the DOM (such as javascript alerts). 

Enter WebDriver 2. Instead of using Proxy Injection, WebDriver automates actions using a browser's native events. This allows for more reliable timing mechanisms as well as the possibility for catching native browser events. Overall, this is great leap forward for automation. 

<h2>Beware Selenium-IDE</h2>

There is just one other caveat with using Selenium from my perspective which should be avoided at all costs - the Selenium IDE. While useful for small, relatively static sites, Selenese tests result in massive duplication, brittle abstractions, and tests that do not encourage reuse. Capture and record tools such as the Selenium IDE are seductively simple to use, but extremely difficult to maintain. Changes to the application require changes to tests themselves. This quickly becomes unmanageable due to the violation of the DRY principle. As such, tools such as Selenium IDE can be classified as semi-automatic as they require a lot of manual intervention when the application changes. Ultimately, semi-automated testing methodologies are doomed to fail simply because the underlying system they depend upon to function ultimately changes. Any system which does not account for application evolution can only capture the requirements at a given point in time. 

<h2>WebDriver is an API</h2>

By favoring programmatic automation, you can leverage general programming principles to create a framework which accounts for the natural evolution of the AUT.

Which brings us to the crux of the matter -<b>WebDriver is an API, not the solution</b>. What does this mean? WebDriver is the means by which automation is achieved, but by itself it does not necessarily give structure to the solution of automating applications in general. The relationships between application components are loosely defined and has no inherent structure in WebDriver. In some cases, the pre-package abstractions are insufficient to reflect the complex relationship between application components. 

<blockquote>This is the role of the framework; to support automation using reusable abstractions against an evolving application.</blockquote>

Automation as a goal does not happen in a vacuum. Applications must be constructed to support automation. As such, coordination with application architects is crucial to support any effort. The framework must be flexible enough to support clearly defined tests whose implementations may change as the application evolves, but whose intent remains the same. To this end, I will describe some of the design decisions I made when creating my testing framework.

<h2>Web Application Automation Concepts</h2>

<h3>The Reusable Element</h3>

Most applications reuse GUI controls; this must be reflected any testing framework. While WebDriver supports finding generic WebElements and manipulating them via additional actions, this requires test code which rely on these methods to be aware of implementation details. In addition, this introduces duplication as soon as you have more than one of a single type of element. By creating an Element abstraction, you can define similar application components by their locators as well as the types of operations they can support for automation. For example, a Text Box is different from a Dropdown. One cannot select items from a Text Box but both may allow for text input. Common behaviors need to be defined in a single representation, while type specific behaviors need to be differentiated.  

Having a reusable Element abstraction allows you to do nifty things like automatic validation of a control based on its type. This is particularly useful for smoke tests. As well, changes to an Element's behavior can easily be propagated throughout the entire testing framework if it is expressed canonically in a single representation. Elements also allow for functional composition. By taking two for more fundamental Elements, you can compose testable aggregate Elements with increasingly sophisticated behavior which still behave as a single functional unit.

You can also localize procedural abstractions such as when an Element is resolved. Ideally, you want to resolve any given just before it is used. This minimizes DOM inconsistencies which arise in applications which re-render output based on post-backs.

<h4>XPath is Regex for the DOM</h4>

Location Strategies are determined by application structure. Ideally, every element has a consistent element ID that is unique to the page where it is located and the same between application invocations. A lot of applications however, do not meet this criteria. Although there are a number of different location strategies supported by WebDriver, the most powerful by far is using XPath.

Tools such as XPather for Firefox allow you to select elements via XPath, but unfortunately use only positional element expressions (such as table[1]/tr[3]/td[2]). Not only are these expressions difficult to read, but they are heavily reliant on the ordering of the DOM. This makes them brittle. 

What is need is a way to specify DOM path expressions which are rooted in the application's vernacular and disambiguate Elements effectively. By leveraging the expressiveness of XPath, you have the ability to specify Elements relative to other Elements. This is useful when labels are distinct from components they decorate. In addition, the annotation method of supplying locators for Elements in WebDriver precludes the ability to use templates to find Elements of a give type which vary only by their identifying characteristic. XPath allows the use of simple String templates. This allows for parameterized Element locators.

The expressiveness of XPath comes at a price. Generally, using XPath for element location is slower than other methods. In addition, not all browsers support XPath natively (Internet Explorer for example). That being said, XPath provides a strategy for taking an existing application and making it amenable to automation. As the application evolves to support unique persistent IDs, these changes can be made globally at the Element abstraction.

For an excellent tutorial on XPath, use the documentation at <a href="http://zvon.org/xxl/XPathTutorial/Output/example1.html">ZVON.org</a>

<h3>The Reusable Page</h3>

Essentially a Page is a container for Elements which are manipulated via automation.  Ideally, Elements associated with a Page should be lazy-initialized on use. In addition, a Page serves as a navigational component. To test something, you need to know where it is and how to get to it. Relationships between pages which define navigational structure depend on the type of application you are trying to automate.

<h4>The Hierarchical Application</h4>

In a Hierarchical Application, each page is located only once in the navigational structure. This type of structure is amenable to programmatic page traversal. In addition, if the application constructs page hierarchies programmatically (as they should), this information can be extracted from the application and the Page relationships can be created via code generation. The <a href="http://www.research.ibm.com/designpatterns/pubs/gg.html">Generation Gap</a> pattern is particularly useful in this regard. C#'s Partial Classes in addition to the ability to nest Classes makes it well suited to solve this problem.

<h4>The Process Oriented Application</h4>

By far the more difficult to automate, the Process Oriented Application has no clear notion of location; Pages relationships are defined in the context of a given process. A wizard-based application is the stereotypical Process Oriented Application. This type of application is not well suited to programmatic page traversal simply due the fact that Pages may have circular dependencies. In this case, it may be difficult to automate the creation of Page relationship.

<h4>The Case Against WebDriver.PageFactory</h4>

PageFactory relies on defaults for the Element lookup strategy that may not be appropriate for the AUT. The use of <b><code>@FindBy</code></b> annotation also makes it difficult to create dynamic Element lookups which are parameterized. The modification of annotations requires the use of reflection which is both cumbersome and expensive. In addition, it is questionable whether caching WebElements via <b><code>@CacheLookup</code></b> is useful given the possibility of StaleElementExceptions.

Instead of the PageFactory, Pages should express their dependencies explicitly in their constructors and hold a lazily-initialized dictionary of Elements with keys based on the language present in the application. If used in combination with the Element abstraction described previously, Element initialization is delegated back to the Element when accessed, not to Page. The Page's element dictionary provides a mechanism for finding Elements; nothing more. Pages constructed in this manner can be invoked directly or through the use of a dependency injector.

<h2>Putting it All Together</h2>

<h3>The Case For the Use of Fluent Interfaces</h3>

From a programming perspective, It is useful to think of the automation framework as serving different clients. There will be programmers responsible for wiring up the framework to the application as opposed to those responsible for wiring up tests to the framework. 

These are two different tasks whose difficulty can be mitigated through the use of <a href="http://en.wikipedia.org/wiki/Fluent_interface">Fluent Interfaces</a>. Page and Element definitions clearly express their requirements. Page navigation and Element access read more descriptively instead of a series of programmatic operations on application component primitives. 

<h3>Degrees of Freedom</h3> 

In the words of Einstein:

<blockquote>"Everything should be made as simple as possible, but not simpler."</blockquote>

All of these abstractions are not designed to introduce unnecessary complexity, but to manage the inherent complexity of automating an application. Application testing must be able to respond to various degrees of freedom which have the ability to destabilize test outcomes. The ultimate goal is reproducibility of the test's intent in the face of change. The following are the different changes which a framework must be resilient to.

<h4>The Application Changes : An Element is added/modified/removed</h4>

To add an element for automation simple requires associating it to a given Page. When an element is modified (such as when it is superseded with a new control with more advanced functionality), it need only be changed in a single location. Changes cascade throughout the entire framework with little work.

<h4>The Application Changes : A Page is added/modified/removed</h4>

If you programmatically determine page relationships, then simply running the code-generation component will create a stub for the new page or remove associated references to a deleted page. Most applications however undergo evolution more often; pages are modified. Elements are added/substracted from pages; this should happen independent of Element evolution. Pages should simply bind Elements that are part of their scope of responsibility.

<h4>The Automation Framework Changes</h4>

While the solution presented here hinges on the use of WebDriver, there is a case to be made for  for framework isolation. All software evolves, and WebDriver is no exception. An automation framework built on WebDriver should also isolate changes to WebDriver itself. Leaking implementation details into tests by directly referencing WebDriver primitives results in fragility when the WebDriver API changes. Ideally, Page or Element bindings should not be directly impacted by changes to the framework itself. 

The concepts of interface inheritance and implementation delegation to wrap primitive framework calls works well to isolate the automation framework from WebDriver changes. In essence, the Element object behaves much like a WebDriver WebElement without exposing any internal implementation details. This allows extension of the original WebDriver API with custom helper methods/interfaces. 

<h4>The Target Web Browsers Change</h4>

There's a good chance that at some point, you will have to test you application against different browsers. To prepare for this eventuality, tests should be created in a web browser agnostic fashion. No test should depend on a specific browser; all automation operations should be done through the RemoteWebDriver/WebElement. By doing so, not only will you be able to run your tests against other browsers, but you will also be able to accommodate future browser updates as support for them is added to WebDriver.

<h2>What's Next?</h2>

Despite having the ability to automate testing, it is infeasible to test everything. Not all tests are equal. The most valuable tests reflect actual application usage. This is the role of specification testing. In the next article, I'll talk about how to use JBehave to fill this role.
]]></description>
         <link>http://www.z1r0.com/2011/08/the_big_picture_part_1.html</link>
         <guid>http://www.z1r0.com/2011/08/the_big_picture_part_1.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Automata</category>
        
          <category domain="http://www.sixapart.com/ns/types#category">SOTA</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">java</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">jbehave</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">jenkins</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">programming</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">webdriver</category>
        
         <pubDate>Mon, 08 Aug 2011 15:28:54 -0700</pubDate>
      </item>
      
      <item>
         <title>The Big Picture : Using WebDriver / JBehave / Jenkins for Automated BDD </title>
         <description><![CDATA[The measure of quality in software is a difficult thing to quantify. We have various tools which enable us to test various aspects of the system, but ultimately I think the measure of quality in a system is the extent to which the software meets the expectations of actual users. 

The human perspective must be injected into any test framework which aims to meet this goal. <b><a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">Behavior Driven Development (BDD)</a></b> fulfills this need by creating specifications modeled in the domain language of the end users. While programmers are adept at manipulating abstractions, this should not be a requirement of end users. They should be able to articulate their expectations in the language most familiar to them. By codifying these expectations as acceptance criteria, the tests become a living document of behaviors rooted in the experience of its users.

Currently there does not exist a single tool which allows us to model these expectations. Instead, we must construct a framework in which user expectations can be used to drive tests against an application. In addition, other factors must be taken into consideration in the design of the framework. Extensibility, modularity, and maintainability are also desirable features. If we assume that the <b>Application Under Test (AUT)</b> will evolve over time to better express the needs of the users, then tests written against the system should be robust to changes which do not affect their original intent. 

The framework that I've constructed uses the latest versions of <b><a href="http://code.google.com/p/selenium/">Selenium/WebDriver 2.0</a></b> in addition to <b><a href="http://jbehave.org/">JBehave 3.4</a></b>. WebDriver provides the automation harness against which test specifications are run against using JBehave. Tests are executed via Jenkins when either the application has changed or new tests are introduced to the system. There are a lot of moving parts to this solution, so I'll break it down into a number of parts:

<h3><a href="http://www.z1r0.com/2011/08/the_big_picture_part_1.html">Part 1 - Plan for Change</a></h3>

All systems evolve over time. As a consequence, not accounting for change makes for brittle solutions. Fix this limitation with the right architecture. 

<h3><a href="http://www.z1r0.com/2011/08/the_big_picture_part_2.html">Part 2 - Testing for the Common Man</a></h3>

The most prominent barrier to testing involves expressing tests without the requirement of programming experience. Having this capability allows business requirements to be expressed by those who will use the system the most.

<h3><a href="http://www.z1r0.com/2011/08/the_big_picture_part_3.html"> Part 3 - Organization is Key</a></h3>

There are a lot of articles out there that show how to use WebDriver/JBehave functionality, but less that address organizing tests into workable groupings. Organization is paramount if we are to create a solution that limits duplication and allows for scalability.

<h3><a href="http://www.z1r0.com/2011/08/the_big_picture_part_4.html">Part 4 - The Automation Environment</a></h3>

BDD works best when we remove the foibles of human intervention from the equation. This however, requires tooling an environment to support continuous deployment. This dovetails well with the concepts of <b><a href="http://en.wikipedia.org/wiki/DevOps">DevOps</a></b>. Virtualization in particular is useful for creating these types of environments.

]]></description>
         <link>http://www.z1r0.com/2011/08/the_big_picture.html</link>
         <guid>http://www.z1r0.com/2011/08/the_big_picture.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Automata</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">java</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">jbehave</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">jenkins</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">programming</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">webdriver</category>
        
         <pubDate>Fri, 05 Aug 2011 09:05:57 -0700</pubDate>
      </item>
      
      <item>
         <title>Snow Leopard Mysteries</title>
         <description><![CDATA[<p>
The upgrade to Snow Leopard left certain parts of my system non-functional. Not good considering that a number of these components are crucial to my development process. Here are the hacks/work-arounds I discovered restoring these services:
</p>

<h3>Subversion</h3>

<p>
Subversion running locally on my MacBook Pro requires that the Remote Login privilege be enabled to support <code><b>svn+ssh</b></code> secure tunneling mode. For some strange reason, the upgrade to OS X 10.6 disabled this privilege breaking my ability to connect to my subversion server. Luckily, my installation notes reminded me of this requirement and after a visit to <b>System Preferences -> Sharing</b>, I was able to restore access.
</p>

<h3>PostgreSQL</h3>

<p>
As I documented with my previous post, the custom PostgreSQL user I created to run the database was deleted by the upgrade. This oversight did not extend to the database installation itself, but recreating the user did not automatically restore database functionality. After a bit of digging around, it seems that my previous PostgreSQL user was assigned a different user id. A peek at the ownership privileges on the database files and directories revealed ownership permissions which did not correspond to a valid system user. A quick <code><b>chmod -R</b></code> fixed the permission problem and allowed PostgreSQL to be started correctly.
</p>

<h3>Fink Commander</h3>

<p>
I've been using Fink Commander to manage packages I've installed on my system over the last two versions of OS X and encountered no obvious upgrade problems when migrating to newer versions of OS X. This changed with Snow Leopard. After upgrading to 10.6, I noticed that despite having updated Fink via the command line, Fink Commander refused to display any package information. Despite an exhaustive search when I first upgraded to Snow Leopard, I was thwarted; I had no clue how to fix this issue. Jump forward a few months and it seems that I was not alone: a solution was finally posted. Due to the number of different <code><b>perl</b></code> binaries packaged with OS X, an explicit path to the older perl binaries was required. Under Fink Commander 0.5.5, this path can be set by navigating to <b>Preferences -> Paths -> Paths to Perl</b>. For OS X 10.6, this value should be <code><b>/usr/bin/perl5.8.9</b></code>. The original post can be found <b><a href="http://finkcommander.sourceforge.net/news/">here</a></b>.
</p>

<p>Mysteries solved.</p>]]></description>
         <link>http://www.z1r0.com/2009/12/snow_leopard_mysteries_solved.html</link>
         <guid>http://www.z1r0.com/2009/12/snow_leopard_mysteries_solved.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Eunichs</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Fink</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">PostgreSQL</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">subversion</category>
        
         <pubDate>Wed, 09 Dec 2009 19:11:34 -0700</pubDate>
      </item>
      
      <item>
         <title>Snow Leopard Gotchas</title>
         <description><![CDATA[<h3>Missing User</h3>

<p>
After upgrading to Snow Leopard (OS X 10.6), I noticed that the PostgreSQL user I created for development using <code><b>dscl</b></code> had suddenly disappeared. Apparently any users that are not created through System Preferences -> User Accounts are excluded during the upgrade process. Strangely, the group associated with this PostgreSQL admin user was still present after the upgrade. It was trivial to restore functionality, but a bit irritating. At least I wasn't stung by the Guest user fiasco that has been finally fixed in 10.6.2. 
</p>
<p>
Now that's out of the way, why is my subversion launchd entry being ignored? Hrmmm ...
</p>

<h3>IR/EyeTV Oddities</h3>

<p>
Another thing I noticed was the complete miscommunication between the IR Remote that came standard with older Macs and EyeTV. IR controls were either mismapped (resulting in strange interactions with EyeTV) or completely non-functional. Thankfully, this was resolved easily with the installation of <a href="http://www.iospirit.com/labs/candelair/">Candalair</a> - an alternative driver for internal Apple IR Receivers. By enabling <b>Leopard Compatibility Mode</b>, things were back to normal. This is obviously a known problem given the very existence of a compatibility mode, but why won't Apple actually fix the problem? 
</p>

<h3>Printing?</h3>

<p>One of the primary reasons for me considering OS X a few years ago was the tight integration of device drivers (for things such as printers) with the OS. I was tired of trying to configure PS emulation for standard photo printers in Linux. Printer configuration was by far the biggest PITA under free *nix varieties. Being able to install a printer painlessly was, for me, a true measure of usability.</p>

<p>Boy, have times changed. Where as my initial experience with 10.4 was the pleasant surprise of "wow that worked the first time", Snow Leopard has changed this process into an all too familiar experience of disappointment. Broken driver support for a slew of existing printers formerly supported by Leopard (10.5) was painful, to say the least. The process of upgrading the drivers with Apple's driver fix failed to notify users that existing print queues would <b>NOT</b> function until they had been recreated was completely obtuse in a way reminiscent of Windows. Oh well, so much for the usability advantage.</p>

<p>To see just how badly this process has devolved, try setting up a Canon Pixma 420 for wireless network printing. A friend of my got one of these with his new iMac, and nothing short of a herculean effort got this printer to work with OS X. Can you say "obscure"?</p>

<h3>Quicktime X Black Screen</h3>

<p>A new and improved Quicktime was supposed to be a boon to Snow Leopard. Unfortunately, right out of the gate, Quicktime X support in Front Row was broken for almost all files. Attempting to play any media files in Front Row resulted in a black screen with no audio or video. 10.6.1 at least restored the ability to play .avi files, but I had to wait until the recent 10.6.2 update to finally have support restored for .mkv's. What happened to releasing a functional product? Given legacy Quicktime support is available in Snow Leopard, wouldn't it have been prudent to wait until this version of Quicktime was ready for prime time before releasing it for public use? At the very least, it shouldn't have broken existing functionality. Where are the QA regression tests?</p>

<h3>At What Cost?</h3>

<p>
I understand the primary motivation behind any public company is profit and Apple is no exception. But what is the cost of relentless push for greater market share if they start to diverge from their core philosophy of "just works"? From a consumer standpoint, there are increasingly compelling reasons to question Apple's current strategies, specially if it comes at the cost of keeping existing customers satisfied. I purchased Apple products because I did not want to contribute to the cycle of "disposable" electronics. Little did I know that by design, this is exactly what I've ended up with.</p>

<p>
<b>Hackintoshes are looking better every day ...</b>
</p>]]></description>
         <link>http://www.z1r0.com/2009/11/snow_leopard_gotchas.html</link>
         <guid>http://www.z1r0.com/2009/11/snow_leopard_gotchas.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Culture Jam</category>
        
          <category domain="http://www.sixapart.com/ns/types#category">Eunichs</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Apple</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">OS X</category>
        
         <pubDate>Tue, 17 Nov 2009 20:18:34 -0700</pubDate>
      </item>
      
      <item>
         <title>Bad Apple</title>
         <description><![CDATA[<p>
OS X 10.6 has been out for quite a while now and in true form, I was quick to upgrade my systems to the latest version in the hopes that it would finally support the full 4GB of memory on my Merom Core2Duo based MacBook Pro. Alas, unless Apple feels particularly beneficent and releases an EFI update which circumvents this limitation, I'm stuck with a 32-bit EFI which also does not address my memory issue. I was aware of this when I purchased the machine almost 3 years ago, but unlike PCs which support firmware updates to work around issues like this, it seems that Apple's strategy of planned obsolescence will have finally caught me in it's clutches. To bad; this issue seems completely contrary to Apple's environmental initiatives if it essentially cripples older machines and relegates them to the scrap heap simply because it refuses to support older architectures. Instead of simply making greener computers, shouldn't they also consider the impact of existing systems they've sold and at the very least keep them out of the landfill for as long as humanly possible? This too can be considered environmental.
</p>

<p>
Another case in point; the iMac I bought around the same time as my Macbook Pro began to exhibit extreme instability due to the faulty cooling design of the GPU in the enclosure. I only found out about this when I attempted to replace the GPU itself. While I can appreciate the design chops that it takes to design increasingly thinner computers, what about actual engineering chops to ensure that the thermal envelope of the enclosure does not lead to premature component death? At the heart of the problem was a single measly cooling fan responsible for the passively relocated heat generated from the CPU and GPU. Active cooling should have been applied separately to the CPU and GPU to ensure adequate cooling. At the very least, the GPU heat sink should have been placed before the CPU heat sink in terms of fan proximity; after all, the CPU is not always busy, but the system cannot function without a working video card. At first, I thought that this problem could have been attributed to faulty capacitors in the NVidia 7300 GT GPU; an issue that has already been addressed in the Mac Pro versions of these cards. But a quick look in the Apple forums revealed that this is a problem endemic in <b>ALL</b> Merom based iMacs (the 20"/24" white plastic varieties manufactured around 2006/2007). 
</p>

<p>
After spending 4 hours disassembling the iMac, I came to the realization : these machines are <b>DESIGNED FOR OBSOLESCENCE</b>. From the obscure torx screws, to the insanely difficult access to components, I got the message loud and clear. <b>These machines do not have field replaceable components</b>. Without this fundamental capability to recycle existing functioning components, what I was left with was a two and a half year old computer that I'd paid a huge premium for that was designed to be rendered unusable by simple hardware failure that is easily remedied in your run-of-the-mill PC.
</p>

<p>
Luckily, my local Mac dealer was willing to get me a replacement GPU and with a little elbow grease, I was able revived my machine. Consider what would have happened if someone else without a technical background was affected. The cost of the replacement card was +$200. Once labour and taxes have been factored in, it would have cost $600 to fix the iMac with a video card that is laughable by today's performance standards. Whether you are discouraged by Apple through the inability to repair your machine with FRUs or the exorbitant cost of an out of warranty repair which makes buying a new machine a "feasible" alternative, the result is the same : electronic waste with a huge environmental impact. My only recommendation going forward for all Apple purchasers is to buy the extended warranty. It is cheaper than a single out of warranty repair, but still seems like an unnecessary cost considering the price premium we initially pay which should equate to "a more reliable" machine.
</p>

<p>
With any luck, the iMac issue will be addressed in a class action suit or a public acknowledgment and an out of warranty replacement/reimbursement. At the time this article was written, Apple still has not acknowledged any culpability with regards to this issue. If you too are facing this issue, add your voice here at <a href="http://www.petitionspot.com/petitions/imacrecall">PetitionSpot</a>.   
</p>

<p>
<b>Shame on you Apple; the greenwashing of environmental issues is a blight on your record. If this is the cost of your current popularity, I smell a worm.</b>
</p>]]></description>
         <link>http://www.z1r0.com/2009/11/bad_apple.html</link>
         <guid>http://www.z1r0.com/2009/11/bad_apple.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Culture Jam</category>
        
          <category domain="http://www.sixapart.com/ns/types#category">NaN</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">Apple</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">hardware</category>
        
         <pubDate>Tue, 17 Nov 2009 18:42:32 -0700</pubDate>
      </item>
      
      <item>
         <title>The New Music</title>
         <description><![CDATA[<p>Listening to music for me has always been about exploration and discovering historical resonance in "new music". It's akin to Bach's Goldberg Variations; each variation contributes its own identity in an entirely unique way. I find that I gravitate to music with this quality; music that unabashedly is influence by the music of my youth.</p>

<p>Unfortunately, traditional means of discovery have been increasingly tainted by commercialism. Thankfully, the Net is a big place with lots of great alternatives. One podcast that I'd like to recommend is NPR's <b>All Songs Considered</b> with Bob Boilen. I can't say I agree with all of his choices, but a few have been bang on. As a tribute to this new find, I'm finally updating my current listening list:</p>

<ul>
<li><b>Asobe Seksu</b> - Transparence</li>
<li><b>Alistar Blaik Bundale</b> - The Day</li>
<li><b>The Gaslight Anthem</b> - The '59 Sound</li>
<li><b>Mesmer</b> - Teenage Dreams</li>
<li><b>White Lies</b> - Taxidermy</li>
<li><b>Gooseflesh</b> - Still Wild</li>
<li><b>Bad Lieutenant</b> - Sink or Swim</li>
<li><b>5 Cent Theatre</b> - Shifting Sands</li>
<li><b>Mumm-Ra</b> - She's Got You High</li>
<li><b>Chambers</b> - Sea Mistress</li>
<li><b>Kurt Vile</b> - Overnite Religion</li>
<li><b>The Coast</b> - Nueva York</li>
<li><b>Kanute</b> - Not Sleeping</li>
<li><b>The Love X Nowhere</b> - Northern Time</li>
<li><b>Phantogram</b> - Mouthful of Diamonds</li>
<li><b>Beat Radio</b> - Memoir of Lightening</li>
<li><b>Land of Talk</b> - May You Never</li>
<li><b>The Exploding Boy</b> - London</li>
<li><b>New Found Land</b> - Leave It Behind</li>
<li><b>Goyte</b> - learnalilgivinanlovin</li>
<li><b>Brite Lite Brite</b> - I Just Want U 2 Myself</li>
<li><b>Miracle Fortress</b> - Hold Your Secrets to Your Heart</li>
<li><b>The Pains of Being Pure at Heart</b> - Higher than the Stars</li>
<li><b>Bye Bye Bicycle</b> - Haby Baby</li>
<li><b>Evan Voytas</b> - Getting Higher</li>
<li><b>Ou Est Le Swimming Pool</b> - Dance the Way I Feel</li>
<li><b>Red Wire Black Wire</b> - Compass</li>
<li><b>Downtown Union</b> - Bright Idea</li>
<li><b>Wild Beasts</b> - Brave Bulging Buoyant Clairvoyants</li>
<li><b>The XX</b> - Blood Red Moon</li>
<li><b>The Ties and the Lies</b> - August is for City Lovers</li>
<li><b>Choir of Young Believers</b> - Action Reaction</li>
<li><b>Gossip</b> - Music for Men</li>
<li><b>The Swell Season</b> - Strict Joy</li>
<li><b>Oliver Schroer</b> - Camino</li>
</ul>

<p>Added to my regular rotation of Muse and Kings of Leon, these tracks ensure that I don't suffer from listening fatigue.</p>
]]></description>
         <link>http://www.z1r0.com/2009/11/the_new_music.html</link>
         <guid>http://www.z1r0.com/2009/11/the_new_music.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">F*?KUDJ</category>
        
          <category domain="http://www.sixapart.com/ns/types#category">Podcasts</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">music</category>
        
         <pubDate>Fri, 06 Nov 2009 20:04:12 -0700</pubDate>
      </item>
      
      <item>
         <title>Testing is Insurance Against Technical Debt</title>
         <description><![CDATA[<ul>
<li><b><a href="http://www.martinfowler.com/bliki/TechnicalDebt.html">Technical Debt</a></b></li>
<li><b><a href="http://sonar.codehaus.org/evaluate-your-technical-debt-with-sonar/">Evaluate Your Technical Debt with Sonar</a></b></li>
</ul>

<p>
I've been ghosting YCombinator's Hacker News and one of the most interesting articles I recently read was by Martin Fowler on the idea of Technical Debt. Coined by Ward Cunningham, the idea is simple - taking a quick and dirty approach to a solution burdens a project with technical debt. This debt is the future effort required to refactor existing code into something more elegant, and ultimately more useful. While the concept explains why people may choose trade-offs in the name of expediency, what struck me most about the metaphor is how the role of testing in the development process could offset this technical debt as a form of "insurance". Tests preserve the original requirements without necessarily committing a developer to a specific implementation. So long as the implementation preserves the requirements, this technical debt can be managed. 
</p>

<p>
One of the most direct measurements of software productivity is the ability to deliver on schedule. By accumulating technical debt, part of your development time is spent either servicing the costs of that debt (by having to code around the original hacks) or paying down the principle (by refactoring). This is the true cost of technical debt. When this debt begins to dwarf the principle value of an application, it is all to easy to default on this debt by slipping deadlines. While tests do nothing to reduce this debt, they prevent it from accumulating additional interest. Without tests, the situation quickly becomes untenable. Instead of Insurance, what you have is a Credit Default Swap. At this point, productivity is a synthetic derivative which has no bearing in reality. All productivity is lost in Complexity. 
</p>

<p>
Put another way, <b>is it possible to pay down technical debt without tests?</b> I'm inclined to think not.
</p>

<p>
Since we're using economic metaphors, I'll use the prophetic words from the Oracle of Omaha which illuminate the cost associated with testing:
</p>

<blockquote>Price is what you pay, value is what you get.</blockquote>

<p>
The price incurred for having to implement and maintain tests far outweighs the value they provide for your application. The only certainty in development is that requirements will change as a program evolves. Tests are insurance against these "known unknowns". 
</p>

<p>As with all my articles, comments (not spam) are welcome.</p>
]]></description>
         <link>http://www.z1r0.com/2009/03/testing_is_insurance_against_t.html</link>
         <guid>http://www.z1r0.com/2009/03/testing_is_insurance_against_t.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Eunichs</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">programming</category>
        
         <pubDate>Tue, 17 Mar 2009 18:10:08 -0700</pubDate>
      </item>
      
      <item>
         <title>Battlestar Galatica - Season 1</title>
         <description><![CDATA[<h4>Spoiler Alert (about a year too late)!!!</h4>

<p>
So I'm 8 episodes into season one of BSG when the first glaring discontinuity raises it ugly head.  Faced with the dilemma of finding a method for being able to detect Cylon infiltrators, the BSG crew serendipitously find a live copy of one of the two known Cylons/Human chimera in existence. Instead of using the Cylon to verify their screening procedure, they eject him out of an airlock. WTF!!! Using Boomer as the first beta candidate could easily have been attributed to a false positive, but comparing  the outcome of her test against a live Cylon baseline would have given them the ability to identify both another Cylon in their midst and repudiate the unsubstantiated claim that Adama was a Cylon. What were the writers thinking?</p> 

<p>
In general, I like the whole re-imagining of the BSG universe with the Manchurian Candidate take on the Cylon infiltrators and the moral quandaries faced by the survivors, but this type of oversight does not bode well for the rest of the series. Hopefully it won't be quite as bad as the season finale I had the unfortunate privilege of watching out of context. When Boomer returns to the Viper without a helmet, the jig's up. Doh! 
</p>
]]></description>
         <link>http://www.z1r0.com/2009/03/battlestar_galatica_-_season_1.html</link>
         <guid>http://www.z1r0.com/2009/03/battlestar_galatica_-_season_1.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Culture Jam</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">BSG</category>
        
         <pubDate>Mon, 16 Mar 2009 21:39:47 -0700</pubDate>
      </item>
      
      <item>
         <title>Fink, ImageMagick, and RMagic Installation for Rails</title>
         <description><![CDATA[<ul>
<li><a href="http://rmagick.rubyforge.org/">RMagic</a></li>
<li><a href="http://rmagick.rubyforge.org/install-osx.html">Installing RMagick on OS X using MacPorts</a></li>
</ul>

<p>It took me a while to figure out how to get Fink to install ImageMagick and the RMagic gem for use with <code><b>attachment_fu</b></code> and I thought I would share my method. From the <code><b>#rubyonrails</b></code> channel on freenode, it seems that I am a Luddite; most users prefer MacPorts. As I've written before, I think there is value in understanding the ports system you are using in OS X and that there be a clear separation between system binaries and those you add yourself. Polluting the <code><b>/usr</b></code> directory with unsupported 3rd party code can only lead to heartache. It also helps to acknowledge the underlying software dependencies in case your production environment varies from development (which is my case). That being said, I've provided the link for those who just <b>have</b> to use MacPorts.</p>

<h4>ImageMagick & Fink</h4>

<p>Before the <code><b>rmagic</b></code> gem can be used, ImageMagick needs to be installed on the machine. Fink is great at being able to build from source and resolving dependencies, but in this case, it took a bit of coercion to get ImageMagick installed. At various points during dependency resolution (for <b>ghostscript</b> and <b>dbus-dev</b>), I was required to abandon FinkCommander and issue the following commands from a Terminal:</p>

<pre>
# fink scanpackages
# sudo apt-get
# sudo apt-get install ghostscript=8.61-5
</pre>

<pre>
# fink scanpackages
# sudo apt-get
# sudo apt-get install dbus-dev=1.2.6-1
</pre>

<p>I'm assuming that order is important in the dependency resolution process, so I included both sets of commands which needed to be run separately at different points in the installation process.</p>

<p>This eventually installed ImageMagick, but unfortunately, the default configuration included the dreaded <code><b>--enable-hdri</b></code> option. Fixing this required digging into Fink source code management internals. By default, Fink keeps ports metadata information in <code><b>.info</b></code> files which are arranged based on stable/unstable trees as well as by function. For ImageMagick, the relevant files were located in the <code><b>/sw/fink/10.5/unstable/main/finkinfo/graphics</b></code> directory. A <code><b>grep</b></code> against the ImageMagick files revealed that <code><b>imagemagick-nox.info</b></code> and <code><b>imagemagic.info</b></code> both contain the option. Simply removing it from these files and rebuilding the ImageMagic port resulted in an <code><b>rmagic</b></code> compatible installation.</p>

<pre>
# fink rebuild imagemagick
</pre> 

<p>There are a number of supplementary packages that are required to build <code><b>rmagic</b></code>; I've included a list of the required ports:
</p>

<pre>
# imagemagick
# imagemagick1-dev
# imagemagick1-shlibs
# imagemagick1-svg
</pre>

<p>In particular, be sure to have the <code><b>imagemagick1-dev</b></code> port installed, otherwise <code><b>Magick-config</b></code> will not be installed which is required for gem installation.</p>

<h4>scripts/plugin fail</h4>

<p>I usually try to follow the path of least resistance - In this case, it was to use the built-in plugin managment utility in Rails. Unfortunately, no matter how I spelled <code><b>rmagic</b></code>, the plugin could not be found in the sources packaged with 2.2.2. I even tried to find the plugin with <code><b>rapt</b></code>. C'est la vie.</p>

<h4>RMagic Installation from Source</h4>

<p>Although the preferred method of installing Rails components is by using <code><b>gem</b></code>, OSX's fonts break the <code><b>rmagic</b></code> tests that run when documentation examples are being generated. This leaves the method of last resort - installing from source. The trick is to change the <code><b>allow-example-errors=no</b></code> parameter to <b>yes</b> in the <code><b>.config</b></code> located in the source directory. Once this is done, run the following commands:</p> 

<pre>
# sudo ruby ./setup.rb
# sudo ruby ./setup.rb install
</pre>

<p>Presto! At this point RMagic should be installed on your system. You can verify by running the following commands (as per the MacPorts installation doc):</p>

<pre>
# irb -rubygems -r RMagick
>> puts Magick::Long_version
This is RMagick 2.9.1 ($Date: 2009/01/12 23:08:35 $) Copyright (C) 2008 by Timothy P. Hunter
Built with ImageMagick 6.4.1 02/25/09 Q16 http://www.imagemagick.org
Built for ruby 1.8.6
Web page: http://rmagick.rubyforge.org
Email: rmagick@rubyforge.org
</pre>

<p>All in all, the process is not unlike a contortionist attempting to pick their nose with their pinky toe .... doable, but certainly uncomfortable. Comments welcome.</p>]]></description>
         <link>http://www.z1r0.com/2009/02/fink_imagemagick_and_rmagic_in.html</link>
         <guid>http://www.z1r0.com/2009/02/fink_imagemagick_and_rmagic_in.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Eunichs</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">programming</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">rails</category>
        
         <pubDate>Thu, 26 Feb 2009 19:12:25 -0700</pubDate>
      </item>
      
      <item>
         <title>RailRoad III</title>
         <description><![CDATA[<h3>Testing</h3>

<p>You can't really follow the the Test Driven Development methodology without writing tests <b>as</b> you develop. While the ROR documentation is fairly complete to get started on building an application, the organization of the documentation (as well as most reference material) seems to put testing at a lower priority in the context of the learning  the Rails platform. It would be nice if the documentation illustrated TDD within the examples as well.</p>

<h4>Fixtures</h4>

<p>Rails provides a facility for quickly creating reproducible testing data through YAML fixture files. The key point of using a fixture as of 2.2.2 is that it is essentially a fully fledged ActiveRecord. When you run a test against a feature, one of the first things that happens is that Rails populates the database table with the fixture information. It is important that your fixture YAML file is syntactically correct - if the data specified in the file references an undefined column or violates a database constraint, Rails will fail to run the test and generate a whack tonne of arcane error messages. Don't do this unless you like to read stack traces.</p>

<p><b>Strange Boolean Behavior.</b> If <code><b>validates_presence_of</b></code>  is placed on a boolean attribute, it can only be assigned <code><b>true</b></code> values within the fixture. Attempting to assign <code><b>false</b></code> to the fixture attribute will break unit tests with the following error:</p>

<pre>
Attribute_name can't be blank.
<false> is not true.
</pre>

<p>In addition, when assigning boolean values within tests, you cannot use the <code><b>false</b></code> keyword. Doing so will create an invalid record. The numeric convention to assign <code><b>true</b></code> or <code><b>false</b></code> is to use <code><b>0</b></code> and <code><b>1</b></code> respectively.</p>

<p><b>Validation of Date versus DateTime Objects.</b> Fixtures can use eRB to embed ruby code within the fixture itself. Unfortunately, when it comes to Date / DateTime attributes, the object returned by the fixture record is database dependent. In most cases, to validate date/time attributes requires using the <code><b>strftime</b></code> comparison. There is no way to get a Date object from a DateTime object. Seems intuitive, but Rails does not provide this facility. For simplicity, I've included the format parameters for posterity:</p>

<pre>
%a - The abbreviated weekday name (``Sun'')
%A - The  full  weekday  name (``Sunday'')
%b - The abbreviated month name (``Jan'')
%B - The  full  month  name (``January'')
%c - The preferred local date and time representation
%d - Day of the month (01..31)
%H - Hour of the day, 24-hour clock (00..23)
%I - Hour of the day, 12-hour clock (01..12)
%j - Day of the year (001..366)
%m - Month of the year (01..12)
%M - Minute of the hour (00..59)
%p - Meridian indicator (``AM''  or  ``PM'')
%S - Second of the minute (00..60)
%U - Week  number  of the current year,
        starting with the first Sunday as the first
        day of the first week (00..53)
%W - Week  number  of the current year,
        starting with the first Monday as the first
        day of the first week (00..53)
%w - Day of the week (Sunday is 0, 0..6)
%x - Preferred representation for the date alone, no time
%X - Preferred representation for the time alone, no date
%y - Year without a century (00..99)
%Y - Year with century
%Z - Time zone name
%% - Literal ``%'' character
</pre>

<pre name="code" class="ruby">
t = Time.now
t.strftime("Printed on %m/%d/%Y")  
    #=> "Printed on 04/09/2003"
t.strftime("at %I:%M%p")            
    #=> "at 08:56AM"
</pre>

<p>Attempting to resolve the fixture issues highlights one of Rails glaring deficiencies - the lack of authoritative, comprehensive documentation. From IRC, to the blogs I researched to troubleshoot these issues, it was apparent that everyone had rather unsubstantiated opinions regarding built-in testing facilities on Rails which were largely incomplete. No application is perfect, but this is a rather obvious omission. </p>

<h4>testhelper.rb</h4>

<p>By default, the <code><b>testhelper.rb</b></code> file has the <code><b>fixtures :all</b></code> parameter enabled. If your scaffold YAML files are not valid, this setting will only throw a lot of unintelligible errors. To build up your test suite one model at a time, it might be useful to simply have a script with <code><b>ruby</b></code> commands to run tests you've already finished. For example, I have a file that I've <code><b>chown</b></code> to be executable which contains commands to run individual tests.</p>

<pre>
ruby unit/model1_test.rb
ruby unit/model2_test.rb
</pre>

<p>The <code><b>testhelper.rb</b></code> file is not all bad. In fact when used in it's primary capacity, it's quite useful. For example, instead of writing custom assertions for my unit tests, I placed a bunch of these in <code><b>testhelper.rb</b></code>. This allows you to follow the DRY (Don't Repeat Yourself) principle an simplify test suite creation. Combined with TextExpander, it's positively stunning how quickly you can create a fairly thorough test suite for a model. I've included some of my custom assertions so that others don't have quite the barrier to entry that I encounter:</p>

<pre name="code" class="ruby">
def assert_not_valid(object, 
    msg="Object is valid when it should be invalid")
  assert(!object.valid?, msg)
end
alias :assert_invalid :assert_not_valid
  
def assert_presence_required(object, field)
  # Test that the initial object is valid
  assert_valid object
   
  # Test that it becomes invalid by removing the field
  temp = object.send field
  object.send "#{field}=", nil
  assert_invalid object
  assert !object.save, 
    "Cannot save record with invalid #{field}"
  assert object.errors.invalid?(field), "Invalid #{field}"
   
  # Make object valid again
  object.send("#{field}=", temp)
end
     
def assert_has_attribute(object, field)
  assert object.has_attribute?(field), 
     "#{object}.klass is missing #{field}"
end
	
def assert_doesnt_have_attribute(object, field)
  assert !object.has_attribute?(field), 
    "#{object}.klass is includes #{field}"
end 
	
def assert_has_readonly_attribute(class_type, field)
  attribute = class_type.readonly_attributes.find { |attr| attr == field }
  assert_not_nil attribute, 
     "#{field} read only attribute was not found."
end
	
def assert_required_length_less_than(object, field, length)
  duplicate = object.dup

  # Valid at length-1
  duplicate.send "#{field}=", "a"*(length-1)
  assert_valid duplicate

  # Valid at length
  duplicate.send "#{field}=", "a"*length
  assert_valid duplicate

  # Invalid at length+1
  duplicate.send "#{field}=", "a"*(length+1)
  assert_invalid duplicate
  assert duplicate.errors.invalid?(field), 
    "Invalid length of : #{field}"
end
	
def assert_inclusion (object, *list)
  assert list.include?(object), "#{object} not in #{list}"	
end
	
def assert_numerical(field)
  assert Integer(field) || Float(field), 
    "The field is not a number."
end
	
def assert_positive_number(field)
  assert_numerical field
  assert field > 0 , "The field is not a positive number."
end
	
def assert_negative_number(field)
  assert_numerical field
  assert field < 0 , "The field is not a negative number."
end
	
def assert_uniqueness_of(object, field)
  duplicate = object.clone
		
  assert_invalid duplicate, 
    "The #{field} attribute must be unique."
  assert duplicate.errors.invalid?(field), "Invalid #{field}"
end
	
def assert_inheritance(object_class, object)
  assert_kind_of object_class, object, 
     "#{object} is not a kind of #{object_class}."
end
</pre>

<h4>Pluralization Conventions</h4>

<p>One of the things that I needed to get used to was the use of pluralization of objects in Rails. From table names in migrations, to polymorphic <code><b>has_many</b></code> associations, being able to specify either single or multiple objects requires being aware of when rails expects plurals. As I mentioned in a previous article, pluralization is controlled through <code><b>inflections.rb</b></code>. This is something to reiterate again, unless you want to learn the hard way.</p>

<p><b>Counter Cache attributes.</b> A counter cache attribute added to a model, is expected to be a pluralized (and possibly inflected) name. For example, to add a <code><b>Comment</b></code> object counter cache to another object requires the <code><b>comments_count</b></code> attribute to be present.</p>

<h4>Limitiations of Single Table Inheritance</h4>

<p>The implementation of object inheritance in Rails can only be described as extremely rudimentary. As per Fowler's description of this pattern, a single table is responsible for all base and subclass data. While this is great for subclasses that simply add attributes to a base class when they are subclassed, this does not work so well when derived subclasses have <b>different</b> attributes.</p>

<p><b>Lack of Class Attribute Encapsulation.</b> Essentially, Rails implementation of STI does not allow subclasses to specify which attributes belong exclusively to themselves. An attribute that is available from one subclass is <b>automatically</b> available to <b>all</b> sibling subclasses. There is no mechanism to disable attribute accessors for certain classes, and enable them for others. It seems the only advantage of STI in rails is to provide convenient way to encapsulate methods and provide a mechanism for storing an object Class name in a table. Not exactly what I would consider Object Oriented .... While it has been suggested that attribute accessors can be overridden within the models, this seems like too much of hack that could have unintended consequences with regards to ActiveRecord behavior. The trade off is to probably code in logic in the classes to ensure that only certain attributes have valid values - the lesser of two evils.</p>

<p><b>Storage of Class Name as the Base Type in Associations.</b> If polymorphic associations are used in conjunction with STI, the <code><b>association_type</b></code> by default must be the base Class name. If it is the actual class name, the association will fail. There are hacks that will allow the actual Class name to be stored by overriding the <code><b>association_type</b></code> attribute, but doing so is less than all encompassing. For example, having <code><b>:dependent => :destroy</b></code> conditions on the association will fail when this hack is implemented. This would then require manually destroying associated objects. Not really a great compromise in my opinion.</p>

<h4>Miscellaneous</h4>

<p>Sometimes things just don't work the way you expect them to. In most cases, it's probably just a case of the documentation not being updated with changes in the code. One particularly pernicious bug was the way in which ActiveRecord deals with <code><b>obj.clone</b></code> versus <code><b>obj.dup</b></code>.</p>

<ul>
<li><a href="http://www.ruby-forum.com/topic/175257">ActiveRecord handling of obj.dup vs obj.clone</a></li>
</ul>

<h4>Limitations actually a Good Thing?</h4>

<ul>
<li><a href="http://www.martinfowler.com/bliki/EnterpriseRails.html">Enterprise Rails</a></li>
</ul>

<p>While these limitations suggest that these areas of Rails are under developed, Martin Fowler has an interesting take on the rigidity shown by the core rails team to solving "enterprise" problems. In his article he suggests that Rails resistance to antiquated conventions which give strength to the existing system. This goes to prove just because you can do something, doesn't mean you should (such as attempting to create an Object Relational Mapper for Rails - RHibernate anyone?).</p>

<p>I reserve the right to withhold judgment ...</p>]]></description>
         <link>http://www.z1r0.com/2009/02/railroad_iii.html</link>
         <guid>http://www.z1r0.com/2009/02/railroad_iii.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Eunichs</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">programming</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">rails</category>
        
         <pubDate>Thu, 12 Feb 2009 21:16:34 -0700</pubDate>
      </item>
      
      <item>
         <title>Professional Developer Tools OS X</title>
         <description><![CDATA[<p>There are just some tools that make life easier. Although I'm a self proclaimed CLI junkie, I think that adhering to fundamentalist attitudes only leads to atrophy. To that end, I'd like to suggest a couple of tools that I grudgingly have to admit are better than their command line equivalents. Its not these tools should be used without knowledge of their CLI counterparts; it's just that having graphical equivalents somehow refines their usage and reduces cognitive resistance when you're in the Flow.
</p>
<h4>Cornerstone</h4>
<p>I can't say enough about Subversion, but trying to keep track of changes between commits and doing diff comparisons with your working set versus the last revision is nothing short of a PITA. Thankfully, there is mature, stable graphical Subversion client for OS X - <a href="xhttp://www.zennaware.com/cornerstone/">Cornerstone</a>. It does a great job of abstracting various Subversion operations and does not suffer from extreme featuritis. Give it a try if your tired of looking up man pages to get just the right <code><b>svn</b></code> syntax.</p>
<h4>Araxis Merge</h4>
<p>While diffing files is old hat, the output is just barely human readable. Too much effort is expended by the user trying to visually grep the output. They say a picture is worth a thousand words, in the in spirit of "Ut pictura poesis" I would have to agree when using a visual diff tool. Having side by side comparisons greatly improves the ability to use diffs in a more coherent manner. Thankfully, Araxis has ported their flagship <a href="http://www.araxis.com/merge_mac/index.html">Merge</a> tool to OS X. Like Cornerstone, the features are implemented with minimal clutter. This allows it to integrate cleanly into an XCode based work flow. With its seemless integration with Cornerstone, checking working copy diffs to a source code repository can't get any easier.</p>
<h4>O'Reilly Safari</h4>
<p>Do your self a favor and forget the forest of books that inevitably become obsolete and sign up for a Safari subscription. Technical books have a limited shelf life. Prevent become antiquated and get the latest documentation without the hassle of having to lug around a dead tree. It's not that I don't like physical books, but the rate at which technical documentation evolves makes it unrealistic to have a well stocked reference library without having to spend a fortune. Combined with the BookBag iPhone app, you can have your cake and eat it too.</p>


]]></description>
         <link>http://www.z1r0.com/2009/01/professional_developer_tools_o.html</link>
         <guid>http://www.z1r0.com/2009/01/professional_developer_tools_o.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Eunichs</category>
        
          <category domain="http://www.sixapart.com/ns/types#category">Ur</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">programming</category>
        
         <pubDate>Sun, 18 Jan 2009 14:02:54 -0700</pubDate>
      </item>
      
      <item>
         <title>RailRoad II</title>
         <description><![CDATA[<p>Here are a few additional notes regarding my experiences with Ruby on Rails. Although there is veritable dearth of information on these topics, the difficulty as ever lies in having a single consolidated reference for these issues. At best, documentation on the web is complete with examples and thoughtful explanations; at worst, it is completely misleading and full of uninformed assumptions.</p>

<h4>Required database.yml parameter : database</h4>

<p>The <code><b>database.yml</b></code> file requires the <code><b>database :</b></code> parameter in order to establish a valid connection to the database for a given user. This parameter was not present in earlier versions of the <code><b>database.yml</b></code> configuration file. See below for more details documentation regarding the PostgreSQL connection adapter parameters.</p>

<h4>Database Adapters: pg versus postgres</h4>

<p>At the time of writing this (against rails 2.2.2), there still seems to be a preference in the Rails framework for the pg driver over the postgres driver. Without the pg driver installed, the following error is displayed to the user :</p>

<pre>
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:74:in `establish_connection': Please install the postgresql adapter: `gem install activerecord-postgresql-adapter` (no such file to load -- pg) (RuntimeError)
	from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:58:in `establish_connection'
	from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:53:in `establish_connection'
	from /Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/initializer.rb:392:in `initialize_database'
	from /Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/initializer.rb:139:in `process'
	from /Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/initializer.rb:112:in `send'
	from /Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/initializer.rb:112:in `run'
	from /Users/mel/Documents/Workspace/vuespace/src/config/environment.rb:13
	from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
	from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
	from /Library/Ruby/Gems/1.8/gems/rails-2.2.2/lib/commands/generate.rb:1
	from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
	from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
	from ./script/generate:3
aleph:src mel$ gem install activerecord-postgresql-adapter
ERROR:  could not find gem activerecord-postgresql-adapter locally or in a repository
aleph:src mel$ sudo gem install activerecord-postgresql-adapter
Password:
ERROR:  could not find gem activerecord-postgresql-adapter locally or in a repository
aleph:src mel$ sudo gem install activerecord-postgresql-adapter
ERROR:  could not find gem activerecord-postgresql-adapter locally or in a repository
aleph:src mel$ sudo gem -r install activerecord-postgresql-adapter
ERROR:  Invalid option: -r.  See 'gem --help'.
aleph:src mel$ sudo gem install -r activerecord-postgresql-adapter
ERROR:  could not find gem activerecord-postgresql-adapter locally or in a repository
</pre>

<p>To install the correct the correct <code><b>pg</b></code> gem, use the following command:</p>

<pre>
# sudo env ARCHFLAGS="-arch i386" gem install pg
</pre>

<p>There seems to be a version difference between the two difference postgres adapeters : <code><b>pg (0.7.9.2008.10.13)</b></code> versus <code><b>postgres (0.7.9.2008.01.28)</b></code>. Only time will tell if this will lead to framework incompatibilities.</p>

<h4>ActiveRecord</h4>

<p>To use the scaffolding in any meaningful manner requires a clear object model that can be used to represent system objects. The <code><b>ActiveRecord::Migration</b></code> class provides detailed usage information that is required to generate these classes and the associated database types. However, details such as the rails type to database type mappings are not easily found in Rails API. The following links highlight the most important features of ActiveRecord objects which will hopefully allow more informed use of this fundamental Rails object.</p>

<ul>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Aggregations/ClassMethods.html">ActiveRecord::Aggregations</a></b> - useful when representing attributes as value objects.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html">ActiveRecord::Associations</a></b> - describes the use of object associations such as many-to-many, inheritance, and polymorphism.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Base.html">ActiveRecord::Base</a></b> - describes the base ActiveRecord object and its associated methods and properties.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Calculations/ClassMethods.html">ActiveRecord::Calculations</a></b> - describes calculation methods available to ActiveRecord objects.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Callbacks.html">ActiveRecord::Callbacks</a></b> - describes the callbacks available during the lifetime of an ActiveRecord object.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/ConnectionHandler.html">ActiveRecord::ConnectionAdapters::ConnectionHandler</a></b> - describes the use of a ConnectionHandler to distribute an object hierarchy amongst different databases.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html">ActiveRecord::ConnectionAdapters::ConnectionPool</a></b> - describes ConnectionPools which can be used to synchronize thread access to a limited number of database connections. The Options section describes the use of the <code><b>:pool</b></code> and <code><b>wait_timeout</b></code> parameters in the <code><b>database.yml</b></code> configuration file.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html">ActiveRecord::ConnectionAdapters::PostgreSQLAdapter</a></b> - describes the <code><b>database.yml</b></code> configuration parameters for PostgreSQL as well as the native datatypes the adapter maps the migration datatypes to. 

<ul>
<li><code><b>:primary_key</b></code> - serial primary key</li>
<li><code><b>:string</b></code> - character varying(255)</li>
<li><code><b>:text</b></code> - text (upto 1GB of multi-byte characters</li>
<li><code><b>:integer</b></code> - integer</li>
<li><code><b>:float</b></code> - float</li>
<li><code><b>:decimal</b></code> - numeric (can be specified with :precision and :scale</li>
<li><code><b>:datetime</b></code> - timestamp without time zone</li>
<li><code><b>:timestamp</b></code> - timestamp without time zone</li>
<li><code><b>:time</b></code> - time</li>
<li><code><b>:date</b></code> - date</li>
<li><code><b>:binary</b></code> - bytea</li>
<li><code><b>:boolean</b></code> - boolean</li>
</ul>

</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Errors.html">ActiveRecord::Errors</a></b> - describes the errors associated with ActiveRecord object operations and how to access them.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Migration.html">ActiveRecord::Migration</a></b> - migration specifics.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Observer.html">ActiveRecord::Observer</a></b> - describes Observer configuration for ActiveRecord objects which implement lifecycle callbacks.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Reflection/ClassMethods.html">ActiveRecord::Reflection</a></b> - ActiveRecord object reflection methods.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Serialization.html">ActiveRecord::Serialization</a></b> - methods which support ActiveRecord object serialization.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Transactions/ClassMethods.html">ActiveRecord::Transactions</a></b> - describes atomic database transactions and their ActiveRecord implementation.</li>
<li><b><a href="http://api.rubyonrails.com/classes/ActiveRecord/Validations/ClassMethods.html">ActiveRecord::Validations</a></b> - describes ActiveRecord object field and condition validation methods.</li>

</ul>

<h4>Object Associations</h4>

<p>As ever, the initial challenge when creating an application is to create an object model that reflects the system being designed without imposing unnecessary limitations. There are a number of relationships that can be modeled through Rails, but it is important to understand both the usage and limitation of these mechanisms.</p>

<ul>
<li><b>Rails only supports Single Table Inheritance</b> - By default only Single Table inheritance is supported by Rails. Essentially, different subclasses are represented by a <code><b>:type</b></code> field in the database table. To avoid confusion, treat <code><b>type</b></code> as a Rails keyword an only use it when you want to model Inheritance.</li><br/>
<li><b>Polymorphism is supported through the <code><b>:has_many :has_one/ :as</b></code> mechanism</b> - common functionality can be shared amongst objects by implementing an interface. This requires the implementing object to have <code><b>interface_id:integer</b></code> and <code><b>interface_type:string</b></code> columns within their database models.</li><br/>
<li><b>The difference between <code><b>:has_one</b></code> and <code><b>:belongs_to</b></code> is largely where the foreign key resides.</b> - The <code><b>:belongs_to</b></code> implementation should have the corresponding foreign key to the referenced object.</li><br/>
<li><b>Many-to-many relationships can be modeled in a number of ways.</b> Direct relationships can be modeled using <code><b>has_and_belongs_to_many</b></code>. If the association needs to be manipulated independently, the <code><b>has_many :through</b></code> relationship will do provided a join table is created to associate the two models.</li><br/>
<li><b>Secondary associations using <code><b>:through</b></code></b>. Both the <code><b>has_one</b></code> and <code><b>has_many</b></code> associations support secondary references through intermediate objects.</li>
</ul>

<h4>Object Hierarchies</h4>

<p>There are built-in mechanisms with Rails to model ordered lists, trees, and hierarchies.</p>

<ul>
<li><code><b>:act_as_list</b></code> - allows a collection of object to function as an ordered list. This requires a <code><b>position</b></code> column within the model.</li>
<li><code><b>:act_as_tree</b></code> - allows a collection to behave as a tree. Requires the <code><b>parent_id</b></code> column within the model.</li>
<li><code><b>:act_as_nested_set</b></code> - allows a collection to behave as a hierarchy. The advantage over <code><b>:act_as_tree</b></code> is that individual nodes can be retrieved with their dependent objects. This model requires the use of the following columns : <code><b>parent_id, lft, rgt</b></code>.</li>
</ul>

<h4>Validations</h4>

<p>Data sanitation is paramount to preventing a whole host of database injection attacks. Always assume that any publicly submitted data can be used to compromise the system. To mitigate these types of attacks, ActiveRecord supports validation of conditions and fields (see above). It is highly recommended that validations be exercised in the testing framework to ensure their proper functioning.</p>]]></description>
         <link>http://www.z1r0.com/2009/01/railroad_ii.html</link>
         <guid>http://www.z1r0.com/2009/01/railroad_ii.html</guid>
        
          <category domain="http://www.sixapart.com/ns/types#category">Eunichs</category>
        
        
          <category domain="http://www.sixapart.com/ns/types#tag">programming</category>
        
          <category domain="http://www.sixapart.com/ns/types#tag">rails</category>
        
         <pubDate>Mon, 12 Jan 2009 20:30:00 -0700</pubDate>
      </item>
      
   </channel>
</rss>

