Here is not very pretty but definitely the easiest way to change invocation order of XCTestCase methods from default alphabetical order to the order they are written in the source file (like GoogleTest does, for example) — with no bullshit like starting test names with a number.

Turns out, the layout of functions in object files generated by Clang matches their order in the source file. Simply sorting test method invocations by addresses of their implementations changes the default alphabetical order to the order they appear in the source code.

The obvious downside is that there is absolutely no guarantee the next clang version will not break it. The layout of object files is entirely up to compiler, and may theoretically change for optimization reasons.

All you need is to add this file to the test project:

//  XCTestCase+HGRunTestsInSourceOrder.m
//  Created by Evgeny Khomyakov on 2016-03-31.

#import <XCTest/XCTest.h>
#import <objc/runtime.h>

@interface XCTestCase (HGRunTestsInSourceOrder)


@implementation XCTestCase (HGRunTestsInSourceOrder)

+ (NSArray*) testInvocations_swizzle_HGRunTestsInSourceOrder;
    NSMutableArray* invocations = [[self testInvocations_swizzle_HGRunTestsInSourceOrder] mutableCopy];
    [invocations sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        Method m1 = class_getInstanceMethod(self, [obj1 selector]);
        Method m2 = class_getInstanceMethod(self, [obj2 selector]);
        void* imp1 = method_getImplementation(m1);
        void* imp2 = method_getImplementation(m2);
        if (imp1 == imp2)
            return NSOrderedSame;
        return (imp1 < imp2 ? NSOrderedAscending : NSOrderedDescending);
    return invocations;

+ (void) load;
    Method originalMethod = class_getClassMethod(XCTestCase.class, @selector(testInvocations));
    Method replacementMethod = class_getClassMethod(XCTestCase.class, @selector(testInvocations_swizzle_HGRunTestsInSourceOrder));
    NSAssert(originalMethod && replacementMethod, @"Bad luck: XCTestCase implementation has changed, this category no longer works.");
    method_exchangeImplementations(originalMethod, replacementMethod);