SLTestController Class Reference
Inherits from | NSObject |
Declared in | SLTestController.h |
Overview
SLTestController
coordinates test execution. Its singleton instance
is the primary interface between the application and the tests.
The methods in the SLTestController (DebugSettings)
category may be useful
in debugging tests.
Tests execute on a background queue. The methods in the SLTestController (AppHooks)
category allow tests to access and manipulate application state in a structured,
thread-safe manner.
For instance, before running the tests, the application delegate could register a “login manager” singleton as being able to programmatically log a test user in:
[[SLTestController sharedTestController] registerTarget:[LoginManager sharedManager]
forAction:@selector(logInWithInfo:)];
When tests need to log in, they could then call loginWithInfo:
:
[[SLTestController sharedTestController] sendAction:@selector(logInWithInfo:)
withObject:@{
@"username": @"john@foo.com",
@"password": @"Hello1234"
}];
This technique has two main benefits:
- It increases the independence of the tests: while one test could (and should) test logging in as a user would, using the UI, the other tests could use the programmatic interface, and not be crippled should the log-in UI break.
- It encourages re-use of your application’s code, while not making the
tests dependent on your application’s structure: in the example above,
the tests need not know which object implements the
logInWithInfo:
action. And, actions can only return objects that can be copied into the testing context, preventing the application and tests from sharing state.
Target actions may be conditionally defined (and registered) only when
integration testing by using the INTEGRATION_TESTING
preprocessor macro.
Tasks
Configuring the Default Timeout
-
defaultTimeout
Subliminal’s timeout.
property
Getting the Shared Test Controller
-
+ sharedTestController
Returns the test controller.
Running Tests
-
– runTests:withCompletionBlock:
Run the specified tests by invoking
runTests:usingSeed:withCompletionBlock:
withSLTestControllerRandomSeed
and the specified completion block. -
– runTests:usingSeed:withCompletionBlock:
Runs the specified tests.
Debugging Tests
-
shouldWaitToStartTesting
Determines whether the controller should wait, after
propertyrunTests:withCompletionBlock:
is invoked, to start testing.
Registering and Deregistering App Hooks
-
– registerTarget:forAction:
Allows application objects to register themselves as being able to perform arbitrary actions.
-
– deregisterTarget:forAction:
Deregisters the target for the specified actions.
-
– deregisterTarget:
Deregisters the target for all actions.
Calling App Hooks
-
– sendAction:
Sends a specified action message to its registered target and returns the result of the message.
-
– sendAction:withObject:
Sends a specified action message to its registered target with an object as the argument, and returns the result of the message.
Properties
defaultTimeout
Subliminal’s timeout.
@property (nonatomic) NSTimeInterval defaultTimeout
Discussion
Various classes within Subliminal use this timeout to control operations that
involve waiting. In particular, this timeout is used to wait for interface elements
to become valid and/or tappable, as required by the tests.
See [SLUIAElement defaultTimeout]
.
The default value is 5 seconds.
Declared In
SLTestController.h
shouldWaitToStartTesting
Determines whether the controller should wait, after runTests:withCompletionBlock:
is invoked, to start testing.
@property (nonatomic) BOOL shouldWaitToStartTesting
Discussion
If this is YES, the test controller will show an alert after
runTests:withCompletionBlock:
is invoked and will not begin testing until
the developer has dismissed that alert.
This allows the developer time to attach the debugger to the tests. That is done by launching the tests, then clicking the following menu items, in Xcode:
Product -> Attach to Process -> <name of testing target, at top>
This setting will only take effect if the target is built in the “Debug”
configuration (with the DEBUG
preprocessor macro set). This is to prevent the
alert from showing when built (in “Release”) for an unattended, continuous
integration run; and to ensure that debug information will be available to the
debugger (whereas the Release configuration may optimize that information away).
To build the tests in Debug, click the the “Scheme” dropdown in the upper left-hand corner, then the following menu items:
<Manage Scheme> -> (double-click) <name of your "Integration Tests" scheme> ->
"Profile" (in the left side-bar)
and change the “Build Configuration” to “Debug”.
Declared In
SLTestController.h
Instance Methods
deregisterTarget:
Deregisters the target for all actions.
- (void)deregisterTarget:(id)target
Parameters
- target
The object to be deregistered.
Discussion
If target is not registered for any actions, this method has no effect.
Declared In
SLTestController+AppHooks.h
deregisterTarget:forAction:
Deregisters the target for the specified actions.
- (void)deregisterTarget:(id)target forAction:(SEL)action
Parameters
- target
The object to be deregistered.
- action
The action message for which the target should be deregistered.
Discussion
If target is not registered for the specified action, this method has no effect.
Declared In
SLTestController+AppHooks.h
registerTarget:forAction:
Allows application objects to register themselves as being able to perform arbitrary actions.
- (void)registerTarget:(id)target forAction:(SEL)action
Parameters
- target
The object to which the action message will be sent.
- action
The message which will be sent to the target. It must take either no arguments, or one
id
-type value conforming to NSCopying. It must return either nothing, or an id-type value conforming to NSCopying.
Discussion
Action messages must take either no arguments, or one id-type value conforming
to NSCopying
. Messages can return either nothing, or id-type values conforming
to NSCopying
. (Copying arguments and return values prevents the tests and
the application from sharing state.)
Each action is performed on the main thread. The argument (if any) is copied, and the copy passed to the target. The return value (if any) is copied, and the copy passed to the caller.
Only one target may be registered for any given action: if a second target is registered for a given action, the first target will be deregistered for that action. Registering the same target for the same action twice has no effect.
The test controller keeps weak references to targets. It’s still recommended for targets to deregister themselves at appropriate times, though.
See Also
Declared In
SLTestController+AppHooks.h
runTests:usingSeed:withCompletionBlock:
Runs the specified tests.
- (void)runTests:(NSSet *)tests usingSeed:(unsigned int)seed withCompletionBlock:(void ( ^ ) ( ))completionBlock
Parameters
- tests
The set of tests to run.
- seed
The seed to use to randomize the tests. If
SLTestControllerRandomSeed
is passed, the test controller will choose a seed.
- completionBlock
An optional block to execute once testing has finished.
Discussion
Tests are run on a background queue. Tests run in ascending order of group,
and then within each group, in an order randomized using the specified seed.
Clients should generally pass SLTestControllerRandomSeed
to let the test controller choose a seed.
If any tests fail, the test controller will log the seed that was used,
so that the run order may be reproduced by invoking this method with that seed.
Tests must support the current platform in order to be run. If any tests are focused, only those tests will be run.
When using a given seed, tests execute in the same relative order regardless of focus. That is, if a set of tests | A, B, C, D | (all unfocused) are run in order [ B, A, C, D ] when using a certain seed, when tests B and C are focused, they will be run in order [ B, C ].
When all tests have finished, the completion block (if provided) will be executed on the main queue. The test controller will then signal UIAutomation to finish executing commands.
Declared In
SLTestController.h
runTests:withCompletionBlock:
Run the specified tests by invoking runTests:usingSeed:withCompletionBlock:
with SLTestControllerRandomSeed
and the specified completion block.
- (void)runTests:(NSSet *)tests withCompletionBlock:(void ( ^ ) ( ))completionBlock
Parameters
- tests
The set of tests to run.
- completionBlock
An optional block to execute once testing has finished.
Declared In
SLTestController.h
sendAction:
Sends a specified action message to its registered target and returns the result of the message.
- (id)sendAction:(SEL)action
Parameters
- action
The message to be performed.
Return Value
The result of the action, if any; otherwise nil
.
Discussion
This method must not be called from the main thread (it is intended to be called by tests).
The message will be performed on the main thread. The returned value (if any) will be copied, and the copy passed to the caller.
Exceptions
- SLAppActionTargetDoesNotExistException
Thrown if, after several seconds' wait, no target has been registered for action, or a registered target has fallen out of scope.
Declared In
SLTestController+AppHooks.h
sendAction:withObject:
Sends a specified action message to its registered target with an object as the argument, and returns the result of the message.
- (id)sendAction:(SEL)action withObject:(id<NSCopying>)object
Parameters
- action
The message to be performed.
- object
An object which is the sole argument of the action message.
Return Value
The result of the action, if any; otherwise nil.
Discussion
This method must not be called from the main thread (it is intended to be called by tests).
The message will be performed on the main thread. The argument will be copied, and the copy passed to the target. The returned value (if any) will be copied, and the copy passed to the calling SLTest.
Exceptions
- SLAppActionTargetDoesNotExistException
Thrown if, after several seconds' wait, no target has been registered for action, or a registered target has fallen out of scope.
Declared In
SLTestController+AppHooks.h