AssertRunsInAnotherThread ?


**Update**
I’ve updated my example below after realizing I left out some important pieces…
**Update**

How do you assert that something runs in a different thread? Or more generically, how do you assert that something runs asynchronously? I need to do this in ObjC but also in Java. The scenario is as follows. I have a WhatzItz object instance stored in myWhatzItz. I tell myWhatzItz to doDisThing. I need to specify that myWhatzItz will doDisThing asynchronously. Experience tells the story that multi-threaded unit tests are dumb, complicated and wrong. So asking myWhatzItz to doDisThing then waiting or polling for completion of doDisThing is not what we want to do here. (It may be what you want to do but it’s not what I want. Since we’re on the same team and since I’m doing the writing you have to want what I want not what you want. I want you to want my wants… forget your wants… your wants are dumb anyhow!)

So how do we design myWhatzItz to doDisThing and doDisThing right? I’m going to suggest an interface… err prototcol. That is an abstraction for what we want to design. In unit testing we stay focused on one thing. All distractions are tossed behind abstractions. So after asking myWhatzItz to doDisThing I need to assert that it uses asynchronous behavior. That brings us a step back. I have to design a dependency on asynchronous behavior first. Right now you’re probably wondering how asynchronous behavior works. Right now I’m ’bout to slap you like Bruce Lee slapped that boy in Enter the Dragon. (Or was that Return of the Dragon? Maybe it was the game of death? Bonus points to the 1st person that gets the movie correct with a link to the clip on YouTube!) “Don’t focus on the finger or you’ll miss the beauty in the sky above!”, says Bruce. We don’t care about how asynchronous behavior works, as its irrelevant to our design. We only care that our work is done asynchronously! So we’ll code this test in ObjectiveC:

#import
@protocol MyAsynchronousBehavior
-(void) performAsynchronously:(SEL) aSelctor onTarget:(id)aTarget withObject:(id)anObject;
@end

@interface MyWhatzItzTest : SenTestCase <MyAsynchronousBehavior>
{
  MyWhatzItz *myWhatzItz;
  SEL selectorPerformed;
  id targetForSelector;
  id parameterForSelector;
  int performAsynchronouslyInvocationCount;
}
@end

@implementation MyWhatzItzTest

-(void) setUp
{
   myWhatzItz = [[MyWhatzItz alloc] init];
   //The test uses the self-shunt pattern to listen for MyAsynchronousBehavior interaction.
   id theAsynchronousBehavior = self;
   myWhatzItz.asynchronousBehavior = theAsynchronousBehavior;
}

-(void) testMyWhatzItzWillAsynchronouslyDoDisThingWhenAskedToDoDatThing
{
  STAssertEquals(performAsynchronouslyInvocationCount, 0, @"Assuming that we haven't been asked to performAsynchronously");
  [myWhatzItz doDatThing];
  STAssertEquals(performAsynchronouslyInvocationCount, 1, @"We SHOULD HAVE been asked to performAsynchronously");
  STAssertEquals(selectorPerformed, @selector(doDisThing:), @"Should have asked to doDisThing using asynchronous behavior.");
  STAssertEquals(targetForSelector, myWhatzItz, @"Should use myWhatzItz for asynchronous execution.");
}
@end
#pragma mark MyAsynchronousBehavior protocol methods
-(void) performAsynchronously:(SEL) aSelctor onTarget:(id)aTarget withObject:(id)anObject
{
  performAsynchronouslyInvocationCount++; selectorPerformed = aSelctor; targetForSelector = aTarget; parameterForSelector = anObject;
}

Supplying the asynchronous behavior becomes a construction/intialization concern, which could be extracted into a wiring framework like Interface Builder (or if you do Java, Springframework). The nice thing is that we can alternate our asynchronous behavior without touching the rest of the project. We can do something quick/dirty like detachThread… and later get more elegant with RunLoops. Today’s tip comes to you (me) completely by accident. I’ve been trying to test drive things in Java and ObjC for several years now and I’ve never got this part quite right. Feel free to share your opinions/experiences with threads and tests.

**Update**
The above example demonstrates a few important unit testing concepts. first it uses the self-shunt pattern to allow the test to become a mock and listen for interactions between the tested object and its collaborator(s). Second, it demonstrates the importance of using tests to carve out the pieces that should NOT be under test. In this situation it’s multi-tasking, however in other scenarios it could be anything from a DBMS to a network call. I could have illustrated an example where I spin up a Thread pool of some sort from within the test started work, paused the main thread and waited for a response. That’s what I’ve done in the past and it becomes extremely complicated and brittle. In stead, I use the elegance of abstraction to make the test 100% predictable, 200% more simplistic, and 300% more maintainable. Where do I get those statistics? The short answer is they’re sequential. (The long story begins yesterday when my 5yr old spontaneously decided to count from 1 to infinity in the middle of our shopping trip. You see, she only recently learned her numbers up to 100 and after getting to 199 we all realized the child’s computational limits as she continued with one hundred one hundred then followed up with one hundred one hundred one, one hundred one hundred two…)
**Update**

5 thoughts on “AssertRunsInAnotherThread ?

  1. I’m having trouble following… How does whatzitz find its way into calling the performAsync… method of the test case, or alternately, if you’re declaring the protocol method on whatzitz, how does whatzitz assign values to the test case’s ivars?

    What about this?

    -(void)setUp {
    // asyncThread and testThread are ivar
    asyncThread = testThread = [NSThread currentThread];

    }

    -(void)testMyWhatzItzIsAsynchronous {
    STAssertEquals( testThread, asyncThread);
    [whatzItz doThatThing];
    STAssertFalse(testThread == asynchThread);
    }

    -(void)perfromAsynchrounously… {
    asyncThread = [NSThread detachNewThreadSelector…
    }

    1. Jamie,

      After several reply and post updates I realized that WordPress likes to swallow angle brackets. I also realized that it’s easier to write code in an editor than it is to write ad-hoc in a blog post. That said I’ll more directly address you questions. The “test” poses as the asynchronous behavior which removes that complexity from the equation. It also leaves us with only the business logic to test. In your example you detach a thread. That is an absolute no-no in unit testing becase you not only test your logic but you test thread management which means you no longer have a unit test. In my example I only listen for the tested objects interaction with asynchronous behavior. That leaves me free from worrying about it. It also leaves me free from coding it. My final object doesn’t spin a thread at all, yet it does work asyncrhonsly by using another object. That leaves me free to do asynchronous work however I please. I can use threads, I can even use processes if my platform allowed. I can shuttle work over the network and have it performed by another machine. I can use thread pools, run loops, green threads or brown threads. I can change it up without touching the rest of my application.

  2. You caught me! I left out two important steps (setUp and protocol adoption in the header) in my haste to post. Let me revise what I have as follows:

    #import
    @protocol MyAsynchronousBehavior
    -(void) performAsynchronously:(SEL) aSelctor onTarget:(id)aTarget withObject:(id)anObject;
    @end
    
    @interface MyWhatzItzTest : SenTestCase <MyAsynchronousBehavior>
    {
      MyWhatzItz *myWhatzItz;
      SEL selectorPerformed;
      id targetForSelector;
      id parameterForSelector;
      int performAsynchronouslyInvocationCount;
    }
    @end
    
    @implementation MyWhatzItzTest
    
    -(void) setUp
    {
       myWhatzItz = [[MyWhatzItz alloc] init];
       //The test uses the self-shunt pattern to listen for MyAsynchronousBehavior interaction.
       id theAsynchronousBehavior = self;
       myWhatzItz.asynchronousBehavior = theAsynchronousBehavior;
    }
    
    -(void) testMyWhatzItzWillAsynchronouslyDoDisThingWhenAskedToDoDatThing
    {
      STAssertEquals(performAsynchronouslyInvocationCount, 0, @"Assuming that we haven't been asked to performAsynchronously");
      [myWhatzItz doDatThing];
      STAssertEquals(performAsynchronouslyInvocationCount, 1, @"We SHOULD HAVE been asked to performAsynchronously");
      STAssertEquals(selectorPerformed, @selector(doDisThing:), @"Should have asked to doDisThing using asynchronous behavior.");
      STAssertEquals(targetForSelector, myWhatzItz, @"Should use myWhatzItz for asynchronous execution.");
    }
    @end
    #pragma mark MyAsynchronousBehavior protocol methods
    -(void) performAsynchronously:(SEL) aSelctor onTarget:(id)aTarget withObject:(id)anObject
    {
      performAsynchronouslyInvocationCount++; selectorPerformed = aSelctor; targetForSelector = aTarget; parameterForSelector = anObject;
    }
    

    In short, the test uses the self-shunt pattern in lieu of mock objects to listen for asynchronous behavior. The point of all of the madness is we don’t “test” asynchronous implementation (that would make it less of a unit test), rather we “specify” asynchronous interaction. Its the difference between asking “does this code run in the background?”, or “does this code perform the proper time slice algorithms by dividing its process up into allocatable portions that can be managed, tracked, started, and halted.” The former question is way more generic and reusable where the latter question is way to specific and has little to do with the task or specification you’re actually working on.

  3. I get it now, it is unfortunate that you’re only testing to see if the selector gets action instead of actually verifying the behavior, but it’s sufficient.

    I assume then you are using some defines to hide the .asynchronousBehavior method on the WhatzItz in Release mode, lest you are giving some punk on the outside a wonderful way to read WhatzItz’s mind.

  4. “…it is unfortunate that you’re only testing to see if the selector gets action instead of actually verifying the behavior,”

    That’s not unfortunate, it’s the best part. In fact, it allows me to verify the behavior of the thing I really wanna verify. You see unit testing means testing in isolation. So if I want to test multi-threading I test it apart from the thing I multi-thread. I’ll have to post a follow up to be more specific.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s