Testes iOS / especificações TDD / BDD e testes de integração e aceitação

229

Quais são as melhores tecnologias para o desenvolvimento orientado a comportamentos no iPhone? E quais são alguns exemplos de projetos de código aberto que demonstram o uso correto dessas tecnologias? Aqui estão algumas opções que encontrei:


Teste de Unidade

Teste :: Estilo da Unidade

  1. OCUnit / SenTestingKit, conforme explicado no Guia de desenvolvimento do iOS: aplicativos de teste de unidade e outras referências do OCUnit .
  2. PEGAR
  3. GHUnit
  4. Google Toolbox para Mac: teste de unidade do iPhone

Estilo RSpec

  1. Kiwi (que também vem com zombaria e expectativas)
  2. Cedro
  3. Jasmine com UI Automation, como mostrado nas especificações hábeis de iOS-Acceptance-Testing

Teste de aceitação

Estilo Selênio

  1. Automação da interface do usuário (funciona no dispositivo)

    ATUALIZAÇÃO: Zucchini Framework parece misturar pepino e automação de interface do usuário! :)

    Postagens antigas do blog:

  2. UISpec com UISpecRunner

  3. FoneMonkey

Estilo Pepino

  1. Frank e iCuke (baseado no pepino encontra conversa no iPhone )

  2. KIF (Mantenha-o funcional) por Square

  3. O Zucchini Framework usa a sintaxe Cucumber para escrever testes e o CoffeeScript para definições de etapas.

Aditivos

Conclusão

Bem, obviamente, não há resposta certa para essa pergunta, mas eis o que eu escolho usar atualmente:

Para testes de unidade, eu costumava usar o OCUnit / SenTestingKit no XCode 4. É simples e sólido. Mas prefiro a linguagem do BDD ao invés do TDD ( por que o RSpec é melhor que o Test :: Unit ?) Porque nossas palavras criam nosso mundo. Então agora eu uso o Kiwi com o preenchimento / preenchimento automático de código ARC e Kiwi . Eu prefiro o Kiwi ao invés do Cedar, porque ele é construído sobre o OCUnit e vem com fósforos e zombarias / tocos no estilo RSpec. ATUALIZAÇÃO: Agora estou analisando o OCMock porque, atualmente, o Kiwi não suporta stubbing de objetos em ponte gratuitos .

Para teste de aceitação, eu uso a UI Automation porque é incrível. Permite gravar cada caso de teste, tornando os testes de gravação automáticos. Além disso, a Apple a desenvolve e, portanto, tem um futuro promissor. Também funciona no dispositivo e na Instruments, o que permite outros recursos interessantes, como mostrar vazamentos de memória. Infelizmente, com a UI Automation, não sei como executar o código Objective-C, mas com Frank e iCuke você pode. Então, testarei o material de nível mais baixo do Objective-C com testes de unidade, ou crio UIButtons apenas para a TESTconfiguração da compilação , que quando clicada, executará o código do Objective-C.

Quais soluções você usa?

Perguntas relacionadas

mattdipasquale
fonte
1
Eu sei há pelo menos alguns meses que laboratórios centrais estavam usando cedro. (hum, acho que isso é óbvio, dado na conta do github). Com o apoio de uma loja como essa, seria a minha escolha.
precisa
1
Este é um bom ponto. Mas, novamente, a Apple sugeriria usar sua estrutura de teste de unidade, não Cedar, não? Então, é Pivotal vs. Maçã. Com qual ir?
ma11hew28
2
Eu escrevi um post comparando Frank, KIF e UIAutomation que pode ser do interesse dos leitores deste tópico sgleadow.github.com/blog/2011/10/26/… #
Stew

Respostas:

53

tl; dr

No Pivotal, escrevemos Cedar porque usamos e amamos o Rspec em nossos projetos Ruby. O cedro não pretende substituir ou competir com o OCUnit; Ele visa trazer a possibilidade de teste no estilo BDD para o Objective C, assim como o Rspec foi pioneiro no teste no estilo BDD no Ruby, mas não eliminou o Test :: Unit. Escolher um ou outro é em grande parte uma questão de preferências de estilo.

Em alguns casos, projetamos o Cedar para superar algumas deficiências na maneira como o OCUnit funciona para nós. Especificamente, queríamos poder usar o depurador em testes, executar testes na linha de comando e nas compilações de IC e obter uma saída de texto útil dos resultados dos testes. Essas coisas podem ser mais ou menos úteis para você.

Resposta longa

A decisão entre duas estruturas de teste, como Cedar e OCUnit (por exemplo), se resume a duas coisas: estilo preferido e facilidade de uso. Vou começar com o estilo, porque isso é simplesmente uma questão de opinião e preferência; a facilidade de uso tende a ser um conjunto de compensações.

As considerações de estilo transcendem a tecnologia ou o idioma que você usa. O teste de unidade no estilo xUnit existe há muito mais tempo do que o teste no estilo BDD, mas o último ganhou rapidamente popularidade, principalmente devido ao Rspec.

A principal vantagem dos testes no estilo xUnit é sua simplicidade e ampla adoção (entre desenvolvedores que escrevem testes de unidade); praticamente qualquer idioma em que você considere escrever código possui uma estrutura no estilo xUnit disponível.

As estruturas no estilo BDD tendem a ter duas diferenças principais quando comparadas ao estilo xUnit: como você estrutura o teste (ou especificações) e a sintaxe para escrever suas afirmações. Para mim, a diferença estrutural é o principal diferenciador. Os testes xUnit são unidimensionais, com um método setUp para todos os testes em uma determinada classe de teste. As classes que testamos, no entanto, não são unidimensionais; geralmente precisamos testar ações em vários contextos diferentes e potencialmente conflitantes. Por exemplo, considere uma classe simples ShoppingCart, com um método addItem: (para os fins desta resposta, usarei a sintaxe do Objective C). O comportamento deste método pode diferir quando o carrinho está vazio, comparado a quando o carrinho contém outros itens; pode ser diferente se o usuário tiver inserido um código de desconto; pode ser diferente se o item especificado puder " • ser enviado pelo método de envio selecionado; etc. Como essas condições possíveis se cruzam, você acaba com um número geometricamente crescente de contextos possíveis; nos testes no estilo xUnit, isso geralmente leva a muitos métodos com nomes como testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies. A estrutura das estruturas no estilo BDD permite que você organize essas condições individualmente, o que eu acho que facilita a cobertura de todos os casos, além de encontrar, alterar ou adicionar condições individuais. Como um exemplo, usando a sintaxe Cedar, o método acima ficaria assim: nos testes no estilo xUnit, isso geralmente leva a muitos métodos com nomes como testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies. A estrutura das estruturas no estilo BDD permite que você organize essas condições individualmente, o que eu acho que facilita a cobertura de todos os casos, além de encontrar, alterar ou adicionar condições individuais. Como um exemplo, usando a sintaxe Cedar, o método acima ficaria assim: nos testes no estilo xUnit, isso geralmente leva a muitos métodos com nomes como testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies. A estrutura das estruturas no estilo BDD permite que você organize essas condições individualmente, o que eu acho que facilita a cobertura de todos os casos, além de encontrar, alterar ou adicionar condições individuais. Como um exemplo, usando a sintaxe Cedar, o método acima ficaria assim:

describe(@"ShoppingCart", ^{
    describe(@"addItem:", ^{
        describe(@"when the cart is empty", ^{
            describe(@"with no discount code", ^{
                describe(@"when the shipping method applies to the item", ^{
                    it(@"should add the item to the cart", ^{
                        ...
                    });

                    it(@"should add the full price of the item to the overall price", ^{
                        ...
                    });
                });

                describe(@"when the shipping method does not apply to the item", ^{
                    ...
                });
            });

            describe(@"with a discount code", ^{
                ...
            });
        });

        describe(@"when the cart contains other items, ^{
            ...
        });
    });
});

Em alguns casos, você encontrará contextos que contêm os mesmos conjuntos de asserções, que podem ser SECADOS usando contextos de exemplo compartilhado.

A segunda principal diferença entre estruturas no estilo BDD e estruturas no estilo xUnit, sintaxe de asserção (ou "correspondente"), simplesmente torna o estilo das especificações um pouco melhor; algumas pessoas realmente gostam, outras não.

Isso leva à questão da facilidade de uso. Nesse caso, cada estrutura tem seus prós e contras:

  • O OCUnit existe há muito mais tempo que o Cedar e é integrado diretamente ao Xcode. Isso significa que é simples criar um novo alvo de teste e, na maioria das vezes, colocar os testes em funcionamento "simplesmente funciona". Por outro lado, descobrimos que, em alguns casos, como a execução em um dispositivo iOS, era quase impossível fazer os testes do OCUnit. A configuração das especificações do Cedar exige um pouco mais de trabalho do que os testes do OCUnit, pois você obtém a biblioteca e o vincula a ela (nunca uma tarefa trivial no Xcode). Estamos trabalhando para facilitar a instalação e todas as sugestões são bem-vindas.

  • O OCUnit executa testes como parte da compilação. Isso significa que você não precisa executar um executável para fazer seus testes; se algum teste falhar, sua construção falhará. Isso torna o processo de execução de testes um passo mais simples, e a saída de teste entra diretamente na janela de saída da compilação, o que facilita a visualização. Optamos por incluir as especificações do Cedar em um executável, que você executa separadamente por alguns motivos:

    • Queríamos poder usar o depurador. Você executa as especificações do Cedar como faria com qualquer outro executável, para poder usar o depurador da mesma maneira.
    • Queríamos testes fáceis de logar no console. Você pode usar o NSLog () nos testes do OCUnit, mas a saída entra na janela de construção, na qual é necessário desdobrar a etapa de construção para lê-la.
    • Queríamos uma leitura fácil dos relatórios de teste, tanto na linha de comando quanto no Xcode. Os resultados do OCUnit aparecem bem na janela de compilação no Xcode, mas a criação a partir da linha de comando (ou como parte de um processo de IC) resulta na saída de teste misturada com muitas outras saídas de compilação. Com fases separadas de construção e execução, o Cedar separa a saída para facilitar a localização da saída de teste. O corredor de teste padrão Cedar copia o estilo padrão de impressão "." para cada especificação aprovada, "F" para especificações com falha etc.) O Cedar também tem a capacidade de usar objetos repórter personalizados, para que você possa produzir resultados da maneira que desejar, com um pouco de esforço.
  • O OCUnit é a estrutura oficial de teste de unidade do Objetivo C e é suportada pela Apple. A Apple possui basicamente recursos ilimitados, portanto, se eles querem algo feito, serão feitos. E, afinal, esta é a sandbox da Apple em que estamos jogando. O outro lado dessa moeda, no entanto, é que a Apple recebe da ordem de um bajilhão de solicitações de suporte e relatórios de erros todos os dias. Eles são extraordinariamente bons em lidar com todos eles, mas podem não ser capazes de lidar com problemas relatados imediatamente ou de maneira alguma. O Cedar é muito mais recente e menos elaborado que o OCUnit, mas se você tiver dúvidas, problemas ou sugestões, envie uma mensagem para a lista de discussão do Cedar ([email protected]) e faremos o possível para ajudá-lo. Além disso, fique à vontade para copiar o código do Github (github.com/pivotal/cedar) e adicionar o que achar que está faltando.

  • A execução de testes do OCUnit em dispositivos iOS pode ser difícil. Honestamente, eu não tentei isso por algum tempo, por isso pode ter ficado mais fácil, mas na última vez que tentei, simplesmente não pude fazer os testes do OCUnit para que qualquer funcionalidade do UIKit funcionasse. Quando escrevemos o Cedar, tínhamos certeza de que poderíamos testar o código dependente do UIKit no simulador e nos dispositivos.

Finalmente, escrevemos o Cedar para testes de unidade, o que significa que não é realmente comparável a projetos como o UISpec. Já faz um bom tempo que eu tentei usar o UISpec, mas entendi que ele estava focado principalmente na condução programada da interface do usuário em um dispositivo iOS. Decidimos especificamente não tentar que o Cedar suporte esses tipos de especificações, já que a Apple estava (na época) prestes a anunciar o UIAutomation.

Adam Milligan
fonte
Obrigado pela resposta completa. Vou ler o livro do RSpec e experimentar o Ceder. Movi o UISpec para a seção Selenium e adicionei o UIAutomation lá também. Estou lendo seu post sobre UIAutomation. Na verdade, Frank parece muito mais simples e legível, além de melhor documentado, então estou pensando em começar com isso. Só espero que seja tão poderoso quanto o UIAutomation. Você diz que UIAutomation pode testar problemas de ciclo de vida. Gostaria de saber se o iCuke também pode ...
ma11hew28
8

Vou ter que jogar Frank na mistura de testes de aceitação. Esta é uma adição relativamente nova, mas funcionou excelente para mim até agora. Além disso, ele está sendo trabalhado ativamente, ao contrário do icuke e dos outros.

raidfive
fonte
5

Para o desenvolvimento orientado a testes, eu gosto de usar o GHUnit , é muito fácil de configurar e funciona muito bem para depuração também.

Richard J. Ross III
fonte
Obrigado. Eu vi esse, mas esqueci de mencionar.
ma11hew28
PLus 1 para GHUnit. usei muito com o OCMock. É muito fácil de configurar, estender e funciona com muita confiabilidade.
Drekka
4

Great List!

Encontrei outra solução interessante para testar aplicativos de interface do usuário do iOS.

Quadro de abobrinha

É baseado em UIAutomation. A estrutura permite escrever cenários centrados na tela no estilo Pepino. Os cenários podem ser executados no Simulador e no dispositivo a partir de um console (é compatível com CI).

As asserções são baseadas em captura de tela. Parece inflexível, mas oferece um bom relatório HTML, com comparação de tela destacada e você pode fornecer máscaras que definem as regiões nas quais você deseja ter uma declaração exata de pixel.

Cada tela deve ser descrita CoffeScripte a ferramenta em si é escrita em ruby. É um tipo de pesadelo poliglota, mas a ferramenta fornece uma boa abstração para UIAutomatione, quando as telas são descritas, é gerenciável mesmo para o controle de qualidade.

user1129998
fonte
Justa! Obrigado. Eu adicionei isso à pergunta acima.
Ma11hew28
2

Eu escolheria o iCuke para testes de aceitação e o Cedar para testes de unidade. UIAutomation é um passo na direção certa para a Apple, mas as ferramentas precisam de melhor suporte para integração contínua; Atualmente, não é possível executar automaticamente testes UIAutomation com Instruments, por exemplo.

SamCee
fonte
1

GHUnit é bom para testes de unidade; para testes de integração, usei o UISpec com algum sucesso (garfo do github aqui: https://github.com/drync/UISpec ), mas estou ansioso para experimentar o iCuke, pois ele promete ser uma configuração leve e você pode use os trilhos testando bens, como RSpec e Pepino.

Roubar
fonte
1

Atualmente, uso specta para rspec como configurações e seu parceiro (como mencionado acima) expecta, que possui inúmeras opções de correspondência impressionantes.

Keith Smiley
fonte
0

Por acaso gosto muito de OCDSpec2, mas sou tendencioso, escrevi OCDSpec e contribui para o segundo.

É muito rápido, mesmo no iOS, em parte porque foi construído do zero, em vez de ser colocado no topo do OCUnit. Também possui uma sintaxe RSpec / Jasmine.

https://github.com/ericmeyer/ocdspec2

Eric Smith
fonte