<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>adams.co.tt blog - tagged with testing</title>
  <id>http://adams.co.tt/</id>
  <updated>2012-04-12</updated>
  <author>
    <name></name>
  </author>
  <entry>
    <title>Duplicate Active Model validation errors</title>
    <link rel="alternate" href="http://adams.co.tt/blog/2012/04/12/duplicate-active-model-validation-errors/"/>
    <id>http://adams.co.tt/blog/2012/04/12/duplicate-active-model-validation-errors/</id>
    <published>2012-04-12</published>
    <updated>2012-04-12</updated>
    <author>
      <name></name>
    </author>
    <content type="html">&lt;p&gt;When attempting to test a model using Active Model validations, I came across a rather odd problem.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'active_model'

class Person
  include ActiveModel::Validations
  validates_length_of :name, :maximum =&amp;gt; 40, :message =&amp;gt; 'name too long'
  attr_reader :name
  def initialize(attrs)
    @name = attrs[:name]
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I was seeing duplicate &lt;code&gt;'name too long'&lt;/code&gt; error messages in the errors hash.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;describe Person do
  describe 'validation' do
    it 'should be invalid if name is too long' do
      person = Person.new(:name =&amp;gt; 'a' * 41)
      person.should_not be_valid
      person.errors[:name].should == ['name too long']
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The above spec failed with the following message:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Failures:

  1) Person validation should be invalid if name is too long
     Failure/Error: person.errors[:name].should == ['name too long']
       expected: ["name too long"]
            got: ["name too long", "name too long"] (using ==)
     # ./spec/person_spec.rb:17
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Some further digging revealed that the &lt;code&gt;Person&lt;/code&gt; was being loaded twice by the &lt;code&gt;require&lt;/code&gt; method. &lt;code&gt;require&lt;/code&gt; was being called twice with two different paths, which both resolved to the file containing &lt;code&gt;Person&lt;/code&gt;. Removing the extra call to &lt;code&gt;require&lt;/code&gt; fixed the issue. This seems to be a problem particular to ruby 1.8.7.&lt;/p&gt;

&lt;p&gt;The runnable code examples reproducing this issue can be found &lt;a href="https://github.com/adscott/validations-spike"&gt;here&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>5 ways to database testing heaven</title>
    <link rel="alternate" href="http://adams.co.tt/blog/2011/08/30/5-ways-to-database-testing-heaven/"/>
    <id>http://adams.co.tt/blog/2011/08/30/5-ways-to-database-testing-heaven/</id>
    <published>2011-08-30</published>
    <updated>2011-08-30</updated>
    <author>
      <name></name>
    </author>
    <content type="html">&lt;p&gt;Many applications are backed by persistent storage in the form of a database. When writing tests for our application, it is important not to forget to include behaviour surrounding interactions with the database. However, writing these tests is often easier said than done. There are common pitfalls, and here I suggest some sensible ways to avoid them. However, the subject matter is rather dry, but hopefully the kittens will help.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/deerwooduk/579761138/" title="Midge cat and computer by dougwoods, on Flickr"&gt;&lt;img src="http://farm2.static.flickr.com/1336/579761138_2384373a41_m.jpg" width="240" height="180" alt="Midge cat and computer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Write tests that &lt;em&gt;only&lt;/em&gt; cover database interactions&lt;/h2&gt;

&lt;p&gt;Testing how your application interacts with the database are, by definition, integration tests. However, many teams make the mistake of testing much more of the application than necessary when testing database interactions. Often, supporting frameworks, such as Spring or Rails, encourage this behaviour. Falling into this trap leads to slow and brittle tests.&lt;/p&gt;

&lt;p&gt;For example, when testing the various permutations of a search operation in a web application, you do not need everything from the controller down wired into your test. Merely instantiate your database access objects and pass them a database connection. You will find that your tests will be quicker and less brittle. Then you can write many more permutations testing your search queries.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/protohiro/85504626/" title="Cats love linux by protohiro, on Flickr"&gt;&lt;img src="http://farm1.static.flickr.com/37/85504626_9a784bf601_m.jpg" width="240" height="192" alt="Cats love linux"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Wrap your tests in transactions&lt;/h2&gt;

&lt;p&gt;Most of the commonly used relational databases support transactions. Transactions are used in applications when an atomic unit of work must be either applied completely or rolled back. They are also used to provide isolation around changes, when a number of applications are connected to a given database. In both of these cases, the intended goal is to commit these changes. We can use transactions in our test to ensure the reverse. We can use transactions to ensure that any changes to data that are made are rolled back.&lt;/p&gt;

&lt;p&gt;This can have a profound effect on your ability to write tests. You no longer need any code to perform data clean up at the end of a test. You no longer need to understand every possible side effect of the code under test. And most importantly, you&amp;rsquo;ll never accidentally leave something behind, that could interact with and break another test.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/dprevite/2279475301/" title="Working From Home by dprevite, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2015/2279475301_99ec29f7d8_m.jpg" width="240" height="180" alt="Working From Home"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Don&amp;rsquo;t couple yourself to your baseline data&lt;/h2&gt;

&lt;p&gt;When writing tests that interact with the database, it is likely that you&amp;rsquo;ll need to use a baseline of data to get those tests running. A baseline is very handy. It means that each test doesn&amp;rsquo;t have to set up a large amount of extraneous data in order to run. This makes your tests much more readable as there is much less noise in them. It also makes them run more quickly if you only set up this baseline once during a test run.&lt;/p&gt;

&lt;p&gt;However, it is very easy to end up with a test that is tightly coupled to this baseline. This can make it very difficult to diagnose test failures, as the data driving the test is unlikely to be visible in your test case. Moreover, it makes your tests much more brittle. Any changes to the baseline can impact a large number of tests.&lt;/p&gt;

&lt;p&gt;To avoid these pain points, always make sure that any data that you make an assertion against, is set up by your test. Do this even if the baseline contains a data set that you could use, as that baseline could change under your feet at any time.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/tahini/5847181243/" title="SDC19305 by Mr Thinktank, on Flickr"&gt;&lt;img src="http://farm4.static.flickr.com/3275/5847181243_1187f9abc3_m.jpg" width="240" height="180" alt="SDC19305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Use triangulation&lt;/h2&gt;

&lt;p&gt;Often when writing applications that interact with a database, it&amp;rsquo;s likely that you&amp;rsquo;ll be using some form of framework. Object relational mapping tools such as Hibernate and ActiveRecord are very powerful in their ability to map database table columns to fields in objects, as well as having many other very useful functions. However, it is useful to test that these mappings have been done properly, particularly if you are in the (unfortunate) situation that your database is acting as an integration point between a number of other applications.&lt;/p&gt;

&lt;p&gt;In this case, it is important to remember to test using some form of triangulation. If you persist and rehydrate an object using the same mappings, then your tests would never catch a defect around mapping a field to the wrong column. In these cases, it&amp;rsquo;s advisable to persist and fetch data using two different mechanisms in your test. Using a little plain old SQL in a Hibernate mapping test won&amp;rsquo;t cost you a great deal in readability and will help prove that your objects are being hydrated and persisted properly.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.flickr.com/photos/tahini/5810915356/" title="SDC19276 by Mr Thinktank, on Flickr"&gt;&lt;img src="http://farm4.static.flickr.com/3037/5810915356_5c3152885c_m.jpg" width="240" height="180" alt="SDC19276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Get your business logic out of the database&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;ve spoken a great deal about the pitfalls of database interaction testing. Even if you&amp;rsquo;re doing all the good things suggested here, you still might find that you&amp;rsquo;re experiencing a great deal of pain. This may simply be because you have too much business logic pushed into the database.&lt;/p&gt;

&lt;p&gt;Stored procedures, named queries, etc. can be great from a performance point of view, but with them you&amp;rsquo;ll need more database interaction testing to support them.&lt;/p&gt;

&lt;p&gt;Database tests are still harder to write, maintain and run. If possible, shifting your business logic to your application will make it much more accessible to your whole team and cheaper to maintain. Often considerations of performance are premature optimisations, and having code that is easier to maintain is also easier to optimise if the need genuinely arises.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Test by feature not story</title>
    <link rel="alternate" href="http://adams.co.tt/blog/2011/06/13/test-by-feature-not-story/"/>
    <id>http://adams.co.tt/blog/2011/06/13/test-by-feature-not-story/</id>
    <published>2011-06-13</published>
    <updated>2011-06-13</updated>
    <author>
      <name></name>
    </author>
    <content type="html">&lt;p&gt;I know it&amp;rsquo;s been said before, but it&amp;rsquo;s such an important and misunderstood point I feel the need to reiterate it.&lt;/p&gt;

&lt;p&gt;Very often, teams build their functional test suites around stories. Every time a new story is played a brand new test is written. Sometimes, the test will even have the story number in the test name.&lt;/p&gt;

&lt;p&gt;This is dangerous for a couple of reasons. &lt;strong&gt;Firstly it encourages duplication in your tests&lt;/strong&gt;. This is because every time a particular application feature is touched, a new test is written, which probably does very similar things to all the other previous tests around the feature. Not only is this a nightmare to maintain, but also it means that your test suite will take forever to run.&lt;/p&gt;

&lt;p&gt;The second reason is, &lt;strong&gt;stories represent changes to features, not the features themselves&lt;/strong&gt;. This means that every time you play a story, you are changing how a piece of functionality works. As a result previous story based tests will fail and will possibly even become redundant. Chasing down these failures incurs a great deal of pain.&lt;/p&gt;

&lt;p&gt;A far more sensible pattern is to build your functional test suite around the features themselves (there&amp;rsquo;s a reason why cucumber test files have the &amp;ldquo;.feature&amp;rdquo; extension). When a story is played, &lt;strong&gt;your test suite is changed or augmented to reflect how the application should work&lt;/strong&gt;. This means redundant or out of date tests are deleted as soon as a story invalidates them. It also means that you only have one set of tests for a given feature, massively reducing duplication.&lt;/p&gt;

&lt;p&gt;Often you&amp;rsquo;ll find that as you write tests to reflect how the application works, your tests will illustrate the business workflows. It will become not only more maintainable, but more accessible to non-technical users, such as non-technical QAs, BAs and the business themselves. This allows them to become involved in the test writing process, and ensures you&amp;rsquo;re testing the features that are most important to them.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Transactions around database tests</title>
    <link rel="alternate" href="http://adams.co.tt/blog/2010/04/01/transactions-around-database-tests/"/>
    <id>http://adams.co.tt/blog/2010/04/01/transactions-around-database-tests/</id>
    <published>2010-04-01</published>
    <updated>2010-04-01</updated>
    <author>
      <name></name>
    </author>
    <content type="html">&lt;p&gt;A database is probably the most common integration point found in software development. Therefore, testing that integration point is key. Ensuring that your queries work and that object relational mapping is configured correctly is key to making sure that the database schema maps to what your application expects.&lt;br /&gt;&lt;br /&gt;The best way to test this is to write tests around your repositories to test that queries return expected results, and that your objects are loaded and persisted as expected.&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;pre&gt;@Test&lt;br /&gt;public void shouldPersistBook() {&lt;br /&gt;    BookRepository repository = new BookRepository();&lt;br /&gt;    Book book = new BookBuilder()&lt;br /&gt;                       .title(&amp;ldquo;War of the Worlds&amp;rdquo;)&lt;br /&gt;                       .author(&amp;ldquo;H. G. Wells&amp;rdquo;)&lt;br /&gt;                       .toBook();&lt;br /&gt;    &lt;br /&gt;    repository.save(book);&lt;br /&gt;    &lt;br /&gt;    List&amp;lt;Record&amp;gt; records = executeQuery(&amp;ldquo;SELECT * FROM book WHERE title = &amp;lsquo;War of the Worlds&amp;rsquo;&amp;rdquo;);&lt;br /&gt;&lt;br /&gt;    assertTrue(records.size() == 1);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;However, there is a problem with this. After running this test, the database will have been modified. Assuming that title is the primary key for this table, this test will fail the second time it is run. An even worse scenario is that the test could pass even if the save method did nothing.&lt;br /&gt;&lt;br /&gt;Therefore, it is sensible to make all tests occur within a transaction. This can be implemented in the setup and tear down of any database tests:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;@Before&lt;br /&gt;public void setUp() {&lt;br /&gt;    executeStatement(&amp;ldquo;START TRANSACTION&amp;rdquo;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@After&lt;br /&gt;public void tearDown {&lt;br /&gt;    executeStatement(&amp;ldquo;ROLLBACK&amp;rdquo;);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This of course only works if your repositories do not use any DDL statements that update the schema, or call commit explicitly. However doing either of these things is very bad, particularly the first, as your application should never be making schema changes. This makes your schema volatile and breaks any transactional wrapping your application may wish to enforce.&lt;/p&gt;
</content>
  </entry>
</feed>
