views:

3139

answers:

4

I'm experimenting with the iPhone SDK and doing some TDD ala Dr. Nic's rbiPhoneTest project. I'm wondering how many, if any, have been successful using this or any other testing framework for iPhone/Cocoa? More important, I'd like to know how to best assert a proprietary binary request/response protocol. The idea is to send a binary request over the network and receive a binary response. Requests and responses are created using byte and'ing and or'ing. I'm using the golden copy pattern to test my request. Here's what I have so far. Don't laugh as I'm new to btoh Objective C and Ruby:

require File.dirname(__FILE__) + '/test_helper'
require 'fileutils'
require 'io'

require "MyModel.bundle"
OSX::ns_import :MyModel

module MyTestExtensions
  def is_absolute_path(path)
    return /^\/.*/.match(path)
  end

  def parent_directory(file)
    dir = file
    if(! is_absolute_path(dir))
      dir = File.expand_path(dir)
    end
    dir = File.dirname(dir)
    assert is_absolute_path(dir), "Expecting an absolute path with #{dir}"
    return dir
  end

  def assert_NSData_contains_bytes_from_file(file, data)
   assert_not_nil data, "Data should not be nil."
    assert data.bytes, "data should have bytes"
    data.length.times { |i|
      expected = file.getc
      assert_not_nil expected, "Expected only #{i} bytes. Actual data contains more."
      actual = data.bytes.int8_at(i)
      assert_equal expected, actual, "Bytes should be equal at offset #{i} expected #{expected.chr} but was #{actual.chr}"
    }
    expected = file.getc
    raise AssertionFailedError, "Expecting #{expected.chr} at offset #{data.length}" unless expected == nil
  end

end

class TestMyModel < Test::Unit::TestCase
include OSX
include MyTestExtensions

  def this_files_dir
    return parent_directory(__FILE__)
  end

  def setup
    @expectedReq = File.new("#{this_files_dir}/ExpectedMyReq")
    # @expectedReq = File.new("#{this_files_dir}/hello.txt")
    assert File.exist?("#{this_files_dir}/ExpectedMyReq"), "The file [#{@expectedReq.path}] should exist."
  end

  def test_my_model_class_exists
    MyModel
  end

  def test_can_init_instance
    assert MyModel.instancesRespondToSelector(:init), "MyModel Should define :init"
  end

  def test_my_model_can_request_my_data
 myModel = MyModel.alloc.init
 data = myModel.requestMyData 'Some query text'
 assert_NSData_contains_bytes_from_file @expectedReq, data
  end

end
+10  A: 

I don’t know much about Ruby or binary protocols, but if You’re interested in unit testing on iPhone, You might want to check out the Google Toolbox for Mac. I am having great success testing my OpenGL ES application with it.

zoul
I agree, this has worked really well for me testing my static classes.http://code.google.com/p/google-toolbox-for-mac/wiki/iPhoneUnitTesting
Dan J
+1  A: 

I've been using the Google framework for a couple of days now and it works pretty well. I haven't gotten too deep yet but so far I believe it to be the safest and best fit for TDD on iPhone. I even managed to get OCMock running with it. Thanx for the tip!.

Cliff
+5  A: 

Cliff, long term you're best investing time in pure ObjC TDD tools. I have used my own rbiphonetest lib in fmdb-migration-manager successfully, but its usefulness is probably limited to libraries etc. Even then there will undoubtly be enough 'works in Cocoa but fails in UIKit' scenarios to make rbiphonetest dubious to use. Hopefully one day RubyCocoa can be built against the Intel UIKit libraries and then it will be very useful and sturdy I think.

Dr Nic
A: 

Nah, I think there's usefulness in driving the shape of high level abstractions. This is no different than what I faced in Blackberry development where you can't bind against ME at all. There we bound to abstractions which gave us the ability to run major pieces of our core logic outside of the device. The last mile is then writing the glue code to glue your implementations onto the ME stack. For instance, we were able to design our image blitting using POJIs (Java interfaces). The interfaces were implemented by mocks that allowed our tests to assert the image was blitting to the correct coordinates. We later wrote a small amount of code to tie the interface to ME canvas. Maybe I'm crazy but there's a gem hidden in code that is forced not bind to a framework or platform.

Cliff