Xcode: macros de pré-processador TEST vs DEBUG

Ao criar um novo projeto com testes de unidade, o Xcode define a configuração de compilation como Debug para o esquema de teste (o mesmo para o esquema de execução).

Devo diferenciar entre os esquemas Run (Command-R) e Test (Command-U)?

Ou seja, devo criar uma nova configuração de compilation chamada teste, adicionar uma macro de pré-processamento TEST = 1 a ele e usá-lo como a configuração de compilation para o esquema de teste em vez disso? Ou, devo apenas manter Run & Test tanto como Debug?

Eu venho de um plano de fundo Ruby / Rails, onde você geralmente tem ambientes de teste, desenvolvimento e produção. Parece-me que Debug é como desenvolvimento e Release é como produção, mas estamos perdendo um teste, e é por isso que estou pensando em fazer sentido adicionar Test.

Comentários? Opiniões? Sugestões?

Eu estou especificamente perguntando isso porque eu quero compilar algo para o teste com:

#ifdef TEST // Do something when I test. #endif 

Eu não acho que isso importa se eu também compilar isso para Debug. Então, eu realmente poderia apenas fazer:

 #ifdef DEBUG // Do something when I run or test. #endif 

Mas, na verdade, só pretendo fazer isso para testes por enquanto. Então, é por isso que estou pensando em diferenciar entre o debug e o teste, mas estou me perguntando por que o Xcode não faz isso por você por padrão? A Apple acha que você não deve diferenciá-los?

Macros de pré-processador não funcionarão, você precisa verificar o ambiente em tempo de execução.

 static BOOL isRunningTests(void) { NSDictionary* environment = [[NSProcessInfo processInfo] environment]; return (environment[@"XCInjectBundleInto"] != nil); } 

(Atualizado para o Xcode 7.3)

Você pode considerar adicionar uma nova configuração de compilation.

No xcode 4, clique no seu projeto no navegador da esquerda.

Na janela principal, clique no seu projeto e, em seguida, selecione a guia “info”.

Clique no botão “+” para adicionar uma nova configuração (você pode chamar o seu “teste” se quiser “).

Agora, clique no seu alvo e vá para a guia de configurações de construção.

Pesquisar “macros de pré-processamento”

Aqui, você pode adicionar macros de pré-processador para sua nova configuração de compilation.

Basta clicar duas vezes em sua nova configuração de “teste” e adicionar TESTING = 1.

Por fim, edite seu esquema de construção. Selecione as opções de teste para o seu esquema. Deve haver um menu suspenso “Configuração de compilation”. Selecione sua configuração de “teste”.

Em vez de criar uma configuração de compilation de teste, eu:

  1. criou um arquivo Tests-Prefix.pch :

     #define TEST 1 #import  #import "CocoaPlant-Prefix.pch" 
  2. entrou no caminho no campo Cabeçalho de prefixo das configurações de compilation do destino de testes.

  3. Adicionamos o seguinte código ao topo de um arquivo que eu criei chamado MyAppDefines.h , importado em MyApp-Prefix.pch :

     #ifdef TEST #define TEST_CLASS NSClassFromString(@"AppDelegateTests") // any test class #define BUNDLE [NSBundle bundleForClass:TEST_CLASS] #define APP_NAME @"Tests" #else #define BUNDLE [NSBundle mainBundle] #define APP_NAME [[BUNDLE infoDictionary] objectForKey:(NSString *)kCFBundleNameKey] #endif 

Isso me permite usar BUNDLE onde quer que eu [NSBundle mainBundle] dizer [NSBundle mainBundle] e também que funcione quando executo Testes.

A importação de SenTestingKit em Tests-Prefix.pch também acelera a compilation do SenTestingKit Framework e permite que eu deixe de fora #import do topo de todos os arquivos de teste.

Decidi adicionar uma verificação para uma variável de ambiente no próprio código, em vez de usar a sugestão isRunningTests () feita por Robert.

  1. Edite o Esquema atual (Esquema de Produto / Esquema / Edição) ou Command + <
  2. Clique na configuração de teste
  3. Clique em Argumentos Desmarque a opção “Usar os argumentos e variables ​​de ambiente da ação Executar
  4. Expanda a seção Variável de ambiente e inclua a variável TESTING com o valor YES
  5. Adicione isto ao seu código em algum lugar e ligue sempre que precisar:
  + (BOOL) isTesting { NSDictionary* environment = [[NSProcessInfo processInfo] environment]; return [environment objectForKey:@"TESTING"] != nil; } 

A canvas deve ficar assim quando terminar.

A tela deve ficar assim

O código acima encontrará a variável de ambiente TESTE quando for executado no modo de teste ou no modo de aplicativo. Este código vai no seu aplicativo, não nos arquivos de teste da unidade. Você pode usar

 #ifdef DEBUG ... #endif 

Para evitar que o código seja executado na produção.

Eu testei muito tempo, encontrei um resultado:

Não apenas você adiciona a macro de pré-processador em seu destino de teste de unidade (você pode ter muitos methods usando variables ​​para teste de unidade apenas e seguir os methods @MattDiPasquale),

mas também Você deve adicionar o arquivo condição complie no seu destino de teste. deveríamos recomplicar esse arquivo, porque você tem uma nova macro de pré-processador para esse arquivo, mas esse arquivo foi criado no destino do aplicativo quando a macro de pré-processamento não foi definida.

Espero que isso ajude você.

A resposta de Robert no SWIFT 3.0:

 func isRunningTests() -> Bool { let environment = ProcessInfo().environment return (environment["XCInjectBundleInto"] != nil); } 

Observe as variables ​​de ambiente para ver se os testes de unidade estão sendo executados. Semelhante à resposta de Robert, mas eu só verifico uma vez por causa do desempenho.

 + (BOOL)isRunningTests { static BOOL runningTests; static dispatch_once_t onceToken; // Only check once dispatch_once(&onceToken, ^{ NSDictionary* environment = [[NSProcessInfo processInfo] environment]; NSString* injectBundle = environment[@"XCInjectBundle"]; NSString* pathExtension = [injectBundle pathExtension]; runningTests = ([pathExtension isEqualToString:@"octest"] || [pathExtension isEqualToString:@"xctest"]); }); return runningTests; } 

No iOS, o [UIApplication sharedApplication] retornará nil quando um teste de unidade estiver em execução.

Versão modificada da resposta de Kev que funciona para mim no Xcode 8.3.2

 +(BOOL)isUnitTest { static BOOL runningTests; static dispatch_once_t onceToken; // Only check once dispatch_once(&onceToken, ^{ NSDictionary* environment = [[NSProcessInfo processInfo] environment]; if (environment[@"XCTestConfigurationFilePath"] != nil && ((NSString *)environment[@"XCTestConfigurationFilePath"]).length > 0) { runningTests = true; } else { runningTests = false; } }); return runningTests; } 

Se você criar uma configuração de compilation Teste e, em seguida, definir a propriedade “Outros Sinalizadores Swift” do seu Destino como “-DTEST”, ela definirá uma macro TEST que funcionará em seu código rápido. Certifique-se de configurá-lo nas configurações de criação do seu destino do aplicativo para que você possa usá-lo no código Swift do seu aplicativo.

Outro ajuste de Sinalizadores Rápidos para DEBUG e TESTE

Então, com este conjunto, você pode testar seu código da seguinte forma:

 func testMacro() { #if !TEST // skipping over this block of code for unit tests #endif }