Testing category on UITextView

66 views
Skip to first unread message

Wesley Moore

unread,
Oct 17, 2010, 10:44:48 PM10/17/10
to Cedar Discussion
Hi all,
I'm trying to write a spec with Cedar to test a category I've added to
UITextView. If I attempt to create a UITextView in the spec it
complains about not being on the main thread:

> Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...

I tried running the entire spec on the main GCD queue as I thought
this was equivalent to the main thread but the same error was raised.

I then thought I might be able to use a mock object but I need the
mock to get the category's behaviour, which can only be done with a
partial mock, which has the same problems as the original attempt.

Does anyone have any thoughts on how I might approach this?

Regards,
Wes

Adam Milligan

unread,
Oct 17, 2010, 11:36:51 PM10/17/10
to cedar-...@googlegroups.com
Hi Wes,

I've run into exactly this problem when testing views that contain
UIWebView objects. UIWebView and UITextView apparently have some
similarities in their internal workings; as far as I can tell they're
both trying to access a thread that the applications sets up and
dedicates to web-related requests; in both cases they try to access
this thread upon instantiation. Unfortunately, access to this thread
is limited to calls from the main thread. Since Cedar runs its specs
in a background thread the very act of trying to instantiate a view
that contains a UIWebView or UITextView causes this error.

There are two (as far as I know) solutions for this. First, you can
run your specs with the CEDAR_HEADLESS_SPECS environment variable set.
This prevents the error because of the odd way the simulator works.
In short, running headless prevents the application from starting the
simulator's UI process. When the UI process isn't running all
UI-related SDK calls simply execute the stubs in the
simulator-specific UIKit SDK, the code never instantiates a real
UIWebView (or UITextView), and the specs don't crash.

The second solution is to stub out the UITextView class yourself.
This is more work, but allows you to keep using the UI spec runner, if
you prefer that. As an example, here are the files I've created to
stub out UIWebView for specs:

http://github.com/pivotal/PivotalCoreKit/blob/master/Spec/UI/UIWebViewSpec%2BSpec.m
http://github.com/pivotal/PivotalCoreKit/blob/master/SpecHelperLib/Extensions/UIWebView%2BSpec.h
http://github.com/pivotal/PivotalCoreKit/blob/master/SpecHelperLib/Extensions/UIWebView%2BSpec.m

I haven't entirely finished the stub, but it should get you going in
the right direction if you want to go that way.

As for running Cedar specs on the main thread, I've been noodling over
the idea of writing a test runner that wil schedule each spec on the
run loop individually, rather than running them all together in the
background. Something like this would also theoretically make it
possible to test asynchronous calls (like performSelector:afterDelay:)
that depend on the run loop. It's just one of those ideas I haven't
had a chance to sit down and write the code for yet.

Wesley Moore

unread,
Oct 18, 2010, 9:59:30 PM10/18/10
to cedar-...@googlegroups.com
Thanks for your help Adam,
I used the ideas in your WebView tests to come up with a pretty small
Spec category that stubs out enough of it to allow me to run the tests
I wanted.

For anyone that's curious you can see what I wrote here:
http://gist.github.com/633459

Wes

Adam Milligan

unread,
Oct 18, 2010, 10:03:12 PM10/18/10
to cedar-...@googlegroups.com
No problem. Do you mind if I take your code and incorporate it into
the SpecHelperLib that contains the UIWebView stub class?

Wesley Moore

unread,
Oct 18, 2010, 10:14:22 PM10/18/10
to cedar-...@googlegroups.com
No I don't mind, go right ahead.

Regards,
Wes

On Tue, Oct 19, 2010 at 1:03 PM, Adam Milligan

Reply all
Reply to author
Forward
0 new messages