RestKit Test Environment
========================

RestKit ships with a testing infrastructure built around OCUnit and
a Ruby testing server environment built on Sinatra. To be able to run the
tests, you need to do a little bit of setup:

1. Install the Ruby Bundler Gem (if necessary): `gem install bundler`
1. Install the other required Gems via Bundler: `bundle`
1. Start the spec server: `rake spec:server`
1. Build and execute the tests within Xcode via the **Product** > **Test**

If the project builds the Specs target correctly and executes the suite, then
you are all set. If there are any issues, you may need to reach out to the mailing
list for help debugging.

Running Tests
-------------

By default, all tests will be executed when your run the **Test** build action. You can selectively
enable/disable which tests are run by holding down the Option Key when selecting **Product** > **Test**
(or type Apple+Option+U).

Writing Tests
-------------

RestKit tests are divided into two portions. There are pure unit tests, which only require the test harness to be
configured and there are integration tests that test the full request/response life-cycle. In general, testing RestKit is very straight-forward. There are only a few items to keep in mind:

1. Tests are implemented in Objective-C and run inside the Simulator or on the Device.
1. Test files live in sub-directories under Specs/ appropriate to the layer the code under test belongs to
1. Tests begin with "test" and should be camel-cased descriptive. i.e. testShouldConsiderA200ResponseSuccessful
1. Expectations are provided using OCHamcrest. Details of the matchers are available on the [OCHamcrest Github Page](http://jonreid.github.com/OCHamcrest/). Generally the matchers are of the form:

        assertThat([someObject someMethod], is(equalTo(@"some value")));
    There is a corresponding `isNot` method available as well.
1. The RKSpecEnvironment.h header includes a number of helpers for initializing and configuring a clean testing environment.
1. OCMock is available for mock objects support. See [http://www.mulle-kybernetik.com/software/OCMock/](http://www.mulle-kybernetik.com/software/OCMock/) for details
1. RestKit is available for 32bit (iOS) and 64bit (OS X) platforms. This introduces some complexity when working with integer data types as NSInteger
and NSUInteger are int's on 32bit and long's on 64bit. Cocoa and OC Hamcrest provide helper methods for dealing with these differences. Rather than using the **Int**
flavor of methods (i.e. `[NSNumber numberWithInt:3]`) use the **Integer** flavor (i.e. `[NSNumber numberWithInteger:]`). This will account for the type differences without
generating warnings or requiring casting.

### Writing Integration Tests

RestKit ships with a Sinatra powered specs server for testing portions of the codebase that require interaction
with a web service. Sinatra is a simple Ruby DSL for defining web server. See the [Sinatra homepage](http://www.sinatrarb.com/) for more details.

The specs server is built as a set of modular Sinatra application in the Specs/Server subdirectory of the RestKit
distribution. When you are adding new integration test coverage to the library, you will need to create a new Sinatra application
to serve your needs. By convention, these are namespaced by functional unit for simplicity. For example, if we are adding a new
cacheing component to the application and want to test the functionality, we would:

1. Create a new file at `Server/lib/restkit/network/cacheing.rb`
1. Create a namespaced Ruby class inheriting from Sinatra::Base to suit our purposes:

        module RestKit
          module Network
            class Cacheing < Sinatra::Base
              get '/cacheing/index' do
                "OK"
              end
            end
          end
        end
1. Open restkit.rb and add a require for the cacheing server:

        require 'restkit/network/cacheing'
1. Open server.rb and add a use directive to the main spec server to import our module:

        class RestKit::SpecServer < Sinatra::Base
          self.app_file = __FILE__
          use RestKit::Network::Authentication
          use RestKit::Network::Cacheing

You now have a functional server-side component to work with. Consult the Sinatra documentation for example on setting
response headers, MIME types, etc. It's all very simple and low ceremony.

You can now switch to the RestKit sources and look the in Specs directory. Keeping with the cacheing example, we would create a new RKCacheingSpec.m file and pull in RKSpecEnvironment.h. From there we can utilize `RKSpecResponseLoader` to asynchronously test
the entire request/response cycle. The response loader essentially spins the run-loop to allow background processing to execute and
simulate a blocking API. The response, objects, or errors generated by processing the response are made available via properties
on the RKSpecResponseLoader object.

Let's take a look at an example of how to use the response loader to test some functionality:

     - (void)testShouldFailAuthenticationWithInvalidCredentialsForHTTPAuthBasic {
        RKSpecResponseLoader* loader = [RKSpecResponseLoader responseLoader];
        RKClient* client = [RKClient clientWithBaseURL:RKSpecGetBaseURL()];
        client.username = RKAuthenticationSpecUsername;
        client.password = @"INVALID";
        [client get:@"/authentication/basic" delegate:loader];
        [loader waitForResponse];
        assertThatBool([loader.response isOK], is(equalToBool(NO)));
        assertThatInt([loader.response statusCode], is(equalToInt(0)));
        assertThatInt([loader.failureError code], is(equalToInt(NSURLErrorUserCancelledAuthentication)));
      }

That's really all there is to it. Consult the existing test code in Specs/ for reference. 

Happy Testing!
