How to implement or imitate the "abstract" class OCUnit?

I have several Objective-C classes organized in an inheritance hierarchy. They all have a common parent who implements all the behavioral relationships common to children. Each child class defines several methods that make it work, and the parent class throws an exception for methods designed to be implemented / overridden by its children. This actually makes the parent pseudo-abstract class (since it is useless in itself), although Objective-C does not explicitly support abstract classes.

The essence of this problem is that I am testing this class hierarchy using OCUnit, and the tests are structured similarly: one test class that performs the general behavior, with a subclass corresponding to each of the tested child classes. However, running test cases on the (abstract) parent class is problematic, as unit tests will not be impressive without key methods. (The alternative of repeating general tests through 5 test classes is not really an acceptable option.)

The imperfect solution I used is to check (in each testing method) whether the instance is a parent test class, and exit if that is. This leads to re-code in each test method, a problem that becomes more and more annoying if one block of tests is very grainy. In addition, all such tests are still being performed and reported as successes, distorting the number of meaningful tests that have actually been performed.

What I would prefer is a way to signal OCUnit "Do not run any tests in this class, but run them only in your child classes." As far as I know, there is no way to do this yet, something similar to a method +(BOOL)isAbstractTestthat I can implement / override. Any ideas on how best to solve this problem with minimal repetition? Does OCUnit have the ability to mark a test class in this way, or is it time to submit a radar?


Edit: Here is a link to the corresponding test code . Note the frequent repetition if (...) return;to run the method, including using a macro NonConcreteClass()for brevity.

+3
5

, , OCUnit, , SenTestCase -performTest:. , " ?" YES, if-statement.

. , , - , .

0

, . invokeTest AbstractTestCase :

- (void) invokeTest {
    BOOL abstractTest = [self isMemberOfClass:[AbstractTestCase class]];
    if(!abstractTest) [super invokeTest];
}
+4

+ (id)defaultTestSuite TestCase.

+ (id)defaultTestSuite {
    if ([self isEqual:[AbstractTestCase class]]) {
        return nil;
    }
    return [super defaultTestSuite];
}
+1

, .

, , . , , , .

OCUnit . :

@implementation MyTestCase {
    RPValue*(^_createInstance)(void);
    MyClass *_instance;
}

+ (id)defaultTestSuite
{
    SenTestSuite *testSuite = [[SenTestSuite alloc] initWithName:NSStringFromClass(self)];

    [self suite:testSuite addTestWithBlock:^id{
        return [[MyClass1 alloc] initWithAnArgument:someArgument];
    }];

    [self suite:testSuite addTestWithBlock:^id{
        return [[MyClass2 alloc] initWithAnotherArgument:someOtherArgument];
    }];

    return testSuite;
}

+ (void)suite:(SenTestSuite *)testSuite addTestWithBlock:(id(^)(void))block
{
    for (NSInvocation *testInvocation in [self testInvocations]) {
        [testSuite addTest:[[self alloc] initWithInvocation:testInvocation block:block]];
    }
}

- (id)initWithInvocation:(NSInvocation *)anInvocation block:(id(^)(void))block
{
    self = [super initWithInvocation:anInvocation];
    if (!self)
        return nil;

    _createInstance = block;

    return self;
}

- (void)setUp
{
    _value = _createInstance();
}

- (void)tearDown
{
    _value = nil;
}
+1

:

- (void)invokeTest {
    [self isMemberOfClass:[AbstractClass class]] ?: [super invokeTest];
}

, AbstractClass.

+1

Source: https://habr.com/ru/post/1735563/


All Articles