ios - Prueba de unidad de pedido utilizando XCTest en Xcode 6
objective-c xcode6 (7)
Me gustaría saber si hay alguna manera de decirle a Xcode que realice pruebas unitarias en un orden específico. Quiero decir no en un mismo archivo de clase XCTestCase, sino entre todos los archivos de clase.
Por ejemplo, quiero ejecutar SitchozrSDKSessionTest antes de ejecutar SitchozrSDKMessageTest.
Miré algunos hilos en la pila o en la documentación de Apple y no he encontrado nada útil.
Gracias por tu ayuda.
Además de la respuesta de andrew-madsen :
testInvocations
un método de clase testInvocations
''inteligente'' que busca los selectores que comienzan con "test" y los ordena alfabéticamente.
Por lo tanto, no es necesario mantener una NSArray
de nombres de selector por separado.
#import <objc/runtime.h>
+ (NSArray <NSInvocation *> *)testInvocations
{
// Get the selectors of this class
unsigned int mc = 0;
Method *mlist = class_copyMethodList(self.class, &mc);
NSMutableArray *selectorNames = [NSMutableArray array];
for (int i = 0; i < mc; i++) {
NSString *name = [NSString stringWithFormat:@"%s", sel_getName(method_getName(mlist[i]))];
if (name.length > 4
&& [[name substringToIndex:4] isEqualToString:@"test"]) {
[selectorNames addObject:name];
}
}
// Sort them alphabetically
[selectorNames sortUsingComparator:^NSComparisonResult(NSString * _Nonnull sel1, NSString * _Nonnull sel2) {
return [sel1 compare:sel2];
}];
// Build the NSArray with NSInvocations
NSMutableArray *result = [NSMutableArray array];
for (NSString *selectorString in selectorNames) {
SEL selector = NSSelectorFromString(selectorString);
NSMethodSignature *methodSignature = [self instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
invocation.selector = selector;
[result addObject:invocation];
}
return result;
}
Nota al pie: se considera una mala práctica hacer que las pruebas unitarias dependan unas de otras
Desde Xcode 7, las subclases de XCTestCase se ordenan alfabéticamente. Si desea asegurarse de que los métodos de prueba en sí también se ejecutan en orden alfabético, debe anular el método de clase testInvocations
y devolver las invocaciones ordenadas por selector.
path/to/xctool.sh /
-workspace YourWorkspace.xcworkspace /
-scheme YourScheme /
test -only SomeTestTarget:SomeTestClass/testSomeMethod
El OP no mencionó si el CI está disponible o si una respuesta de la línea de comando sería suficiente. En esos casos, he disfrutado usando xctool [1]. Tiene sintaxis para ejecutar pruebas a un solo método de prueba:
@interface MyTestCase : XCTestCase
@end
@implementation MyTestCase
+ (NSArray<NSInvocation *> *) testInvocations
{
return [[super testInvocations] sortedArrayUsingComparator:^NSComparisonResult(NSInvocation *invocation1, NSInvocation *invocation2) {
return [NSStringFromSelector(invocation1.selector) compare:NSStringFromSelector(invocation2.selector)];
}];
}
- (void) test_01
{
}
- (void) test_02
{
}
@end
Haré esto para asegurarnos de probar primero los elementos que creemos que son más fáciles.
1. [] facebook / xctool: un reemplazo para xcodebuild de Apple que facilita la creación y prueba de aplicaciones iOS o OSX. ; ; https://github.com/facebook/xctool
Es cierto que actualmente (a partir de Xcode 7), los métodos de XCTestCase se ejecutan en orden alfabético, por lo que puede forzar un orden para ellos nombrándolos inteligentemente. Sin embargo, este es un detalle de implementación y parece que podría cambiar.
Una (y es de esperar) una manera menos frágil de hacer esto es anular +[XCTestCase testInvocations]
y devolver sus propios objetos NSInvocation
en el orden en que desea que se ejecuten las pruebas.
Algo como:
+ (NSArray *)testInvocations
{
NSArray *selectorStrings = @[@"testFirstThing",
@"testSecondThing",
@"testAnotherThing",
@"testLastThing"];
NSMutableArray *result = [NSMutableArray array];
for (NSString *selectorString in selectorStrings) {
SEL selector = NSSelectorFromString(selectorString);
NSMethodSignature *methodSignature = [self instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
invocation.selector = selector;
[result addObject:invocation];
}
return result;
}
Por supuesto, la desventaja aquí es que tiene que agregar manualmente cada método de prueba a esto en lugar de que sean recogidos automáticamente. Hay algunas maneras de mejorar esta situación. Si solo necesita ordenar algunos de sus métodos de prueba, no todos, en su anulación de +testInvocations
, puede llamar a super, filtrar los métodos que ha ordenado manualmente y luego pegar el resto hasta el final. de la matriz que devuelve. Si necesita solicitar todos los métodos de prueba, aún puede obtener el resultado de llamar a super y verificar que todos los métodos seleccionados automáticamente están cubiertos por su resultado ordenado creado manualmente. Si no, puede afirmar, causando una falla si ha olvidado agregar algún método.
Dejo de lado la discusión de si es "correcto" escribir pruebas que deben ejecutarse en un cierto orden. Creo que hay escenarios raros en los que eso tiene sentido, pero otros pueden estar en desacuerdo.
Por ejemplo, solo puede cambiar el nombre de los archivos de prueba en su proyecto de la siguiente manera:
SitchozrSDKSessionTest -> t001_SitchozrSDKSessionTest
SitchozrSDKMessageTest -> t002_SitchozrSDKMessageTest
Xcode trata los archivos usando orden alfabético.
Todo está ordenado alfabéticamente (clases y métodos). Entonces, cuando necesite que se ejecuten algunas pruebas al final, solo cambie el nombre de Clase o Método (para el ejemplo (desagradable) con el prefijo ''z_'').
Entonces ... Tienes nombres de clase:
MyAppTest1
-testMethodA
-testMethodB
MyAppTest2
-testMethodC
-testMethodD
y corren en este orden. Si necesita ejecutar MyAppTest1 como segundo, simplemente cambie el nombre para que su nombre aparezca alfabéticamente después de MyAppTest2 (z_MyAppTest1) y se ejecutará (igual para el método):
MyAppTest2
-a_testMethodD
-testMethodC
z_MyAppTest1
-testMethodA
-testMethodB
También por favor tome el nombre como ejemplo :)
su orden por nombres de funciones ordena letras, no importa cómo lo ordene en su código. p.ej:
-(void)testCFun(){};
-(void)testB2Fun(){};
-(void)testB1Fun(){};
la orden de ejecución real es:
- testB1Fun llamado
- testB2Fun llamado
- testCFun llamado