Repository: realm/realm-swift
File: Realm/Tests/SchemaTests.m (Objective-C)

Code before:
//
//  SchemaTests.m
//  Realm
//
//  Created by Jesper Zuschlag on 17/06/14.
//  Copyright (c) 2014 Realm. All rights reserved.
//

#import <XCTest/XCTest.h>
#import "RLMTestCase.h"

@interface SchemaTests : RLMTestCase

@end

@implementation SchemaTests

- (void)testObjectSchema
{
    // Setting up some test data
    
    NSArray *expectedTypes = @[@"Company",
                               @"AgeObject",
                               @"KeyedObject",
                               @"AggregateObject",
                               @"AllTypesObject",
                               @"RLMTestObject",
                               @"SimpleObject",
                               @"PersonObject",
                               @"SimpleMisuseObject",
                               @"OwnerObject",
                               @"RLMDynamicObject",
                               @"EnumPerson",
                               @"CircleObject",
                               @"MixedObject",
                               @"DogObject",
                               @"IndexedObject",
                               @"TestQueryObject",
                               @"ArrayPropertyObject",
                               @"BaseClassTestObject",
                               @"CustomAccessors",
                               @"NoDefaultObject",
                               @"PersonQueryObject",
                               @"AllPropertyTypesObject",
                               @"IgnoredURLObject",
                               @"DefaultObject"];
    
    NSString *unexpectedType = @"__$ThisTypeShouldNotOccur$__";
    
    // Getting the test realm
    RLMRealm *realm = [self realmWithTestPath];
    RLMSchema *schema = realm.schema;
    
    // Test 1: Do objectSchema returns the right number of object schema?
    NSArray *objectSchemas = schema.objectSchema;
    
    XCTAssert(objectSchemas.count == 25, @"Expecting 25 object schemas in database");
    
    // Test 2: Does the object schema array contained the expected shema?
    for(NSString *expectedType in expectedTypes) {
        [self performIndexAccessTestOnObjectSchemas:objectSchemas
                                     withSchemaName:expectedType
                                      expectedCount:1];
    }

    [self performIndexAccessTestOnObjectSchemas:objectSchemas
                                 withSchemaName:unexpectedType
                                  expectedCount:0];
    
    // Test 3: Test querying object schema using schemaForClassName:
    for(NSString *expectedType in expectedTypes) {
        [self performQueryAccessTestOnRealmSchemas:schema
                                    withSchemaName:expectedType
                                          expected:YES];
    }

    [self performQueryAccessTestOnRealmSchemas:schema
                                withSchemaName:unexpectedType
                                      expected:NO];
    
    // Test 4: Test querying object schema using subscription
    for(NSString *expectedType in expectedTypes) {
        [self performSubscriptionAccessTestOnRealmSchemas:schema
                                           withSchemaName:expectedType
                                                 expected:YES];
    }
    [self performSubscriptionAccessTestOnRealmSchemas:schema
                                       withSchemaName:unexpectedType
                                             expected:NO];
    
    NSLog(@"Object schemas %@", objectSchemas);
}

- (void)performIndexAccessTestOnObjectSchemas:(NSArray *)objectSchemas withSchemaName:(NSString *)className expectedCount:(NSUInteger)expectedCount
{
    NSUInteger occurrenceCount = 0;
    
    for(RLMObjectSchema *objectSchema in objectSchemas) {
        if([objectSchema.className isEqualToString:className]) {
            occurrenceCount++;
        }
    }
    
    XCTAssert(occurrenceCount == expectedCount, @"Expecting %lu occurrence of object schema for type %@ found %lu", expectedCount, className, (unsigned long)occurrenceCount);
}

- (void)performQueryAccessTestOnRealmSchemas:(RLMSchema *)realmSchema withSchemaName:(NSString *)className expected:(BOOL)expected
{
    BOOL found = [realmSchema schemaForClassName:className] != nil;
    
    if(expected) {
        XCTAssert(found, @"Expecting to find type %@ in realm using query, found none", className);
    }
    else {
        XCTAssert(!found, @"Expecting not to find type %@ in realm using query, found one", className);
    }
}

- (void)performSubscriptionAccessTestOnRealmSchemas:(RLMSchema *)realmSchema withSchemaName:(NSString *)className expected:(BOOL)expected
{
    BOOL found = realmSchema[className] != nil;
    
    if(expected) {
        XCTAssert(found, @"Expecting to find type %@ in realm using subscription, found none", className);
    }
    else {
        XCTAssert(!found, @"Expecting not to find type %@ in realm using subscription, found one", className);
    }
    
}

@end


Review comment (suggestion):
Code factoring can have two different purposes; reuse and/or separation of concern. You can write your program in one function, but I favour splitting it into manageable elements even if only called once (the old rule of thumbs from way back 80x24 consoles said one function should fit one screen ;-)


Code after:
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2014 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#import <XCTest/XCTest.h>
#import "RLMTestCase.h"

@interface SchemaTests : RLMTestCase

@end

@implementation SchemaTests

- (void)testObjectSchema
{
    // Setting up some test data
    
    // Due to the automatic initialization of a new realm with all visible classes inheriting from
    // RLMObject, it's difficult to define test cases that verify the absolute correctness of a
    // realm's current type catalogue unless its expected configuration is known at compile time
    // (requires that the set of expected types is always up-to-date). Instead, only a partial
    // verification is performed, which only requires the availability of a well-defined subset of
    // types and ignores any other types that may be included in the realm's type catalogue.
    // If a more fine-grained control with the realm's type inclusion mechanism is introduced later
    // on, these tests should be altered to verify all types.
    
    NSArray *expectedTypes = @[@"QueryObject",
                               @"PersonObject",
                               @"DynamicObject",
                               @"DogObject",
                               @"AggregateObject",
                               @"ArrayPropertyObject",
                               @"OwnerObject",
                               @"CompanyObject",
                               @"MixedObject",
                               @"AllTypesObject",
                               @"EmployeeObject",
                               @"StringObject",
                               @"IntObject",
                               @"IgnoredURLObject",
                               @"BaseClassStringObject",
                               @"IndexedObject",
                               @"CustomAccessorsObject",
                               @"DefaultObject",
                               @"CircleObject"];
    
    NSString *unexpectedType = @"__$ThisTypeShouldNotOccur$__";
    
    // Getting the test realm
    RLMRealm *realm = [self realmWithTestPath];
    RLMSchema *schema = realm.schema;
    
    // Test 1: Does the objectSchema return the right number of object schemas?
    NSArray *objectSchemas = schema.objectSchema;
    
    XCTAssertTrue(objectSchemas.count >= expectedTypes.count, @"Expecting %lu object schemas in database found %lu", (unsigned long)expectedTypes.count, (unsigned long)objectSchemas.count);
    
    // Test 2: Does the object schema array contain the expected schemas?
    NSUInteger identifiedTypesCount = 0;
    for (NSString *expectedType in expectedTypes) {
        NSUInteger occurrenceCount = 0;
        
        for (RLMObjectSchema *objectSchema in objectSchemas) {
            NSLog(@"Scheme %@", objectSchema.className);
            if ([objectSchema.className isEqualToString:expectedType]) {
                occurrenceCount++;
            }
        }
        
        XCTAssertEqual(occurrenceCount, (NSUInteger)1, @"Expecting single occurrence of object schema for type %@ found %lu", expectedType, occurrenceCount);
        
        if (occurrenceCount > 0) {
            identifiedTypesCount++;
        }
    }

    // Test 3: Does the object schema array contains at least the expected classes
    XCTAssertTrue(identifiedTypesCount >= expectedTypes.count, @"Unexpected object schemas in database. Found %lu out of %lu expected", identifiedTypesCount, expectedTypes.count);
    
    // Test 4: Test querying object schemas using schemaForClassName: for expected types
    for (NSString *expectedType in expectedTypes) {
        XCTAssertNotNil([schema schemaForClassName:expectedType], @"Expecting to find object schema for type %@ in realm using query, found none", expectedType);
    }

    // Test 5: Test querying object schemas using schemaForClassName: for unexpected types
    XCTAssertNil([schema schemaForClassName:unexpectedType], @"Expecting not to find object schema for type %@ in realm using query, did find", unexpectedType);
    
    // Test 6: Test querying object schemas using subscription for unexpected types
    for (NSString *expectedType in expectedTypes) {
        XCTAssertNotNil(schema[expectedType], @"Expecting to find object schema for type %@ in realm using subscription, found none", expectedType);
    }
    
    // Test 7: Test querying object schemas using subscription for unexpected types
    XCTAssertNil(schema[unexpectedType], @"Expecting not to find object schema for type %@ in realm using subscription, did find", unexpectedType);
}

@end