TDD - Outside In vs Inside Out

53

Qual é a diferença entre a criação de um aplicativo Outside In vs a criação de Inside Out usando TDD?

Estes são os livros que li sobre TDD e testes de unidade:
Desenvolvimento Orientado a Testes: Por exemplo
Desenvolvimento Orientado a Testes: Um Guia Prático: Um Guia Prático
Soluções do Mundo Real para o Desenvolvimento de Frameworks PHP de Alta Qualidade e
Desenvolvimento Orientado a Testes de Aplicativos na Microsoft.
Padrões de teste do NET xUnit: Refatorando o código de teste
A arte do teste de unidade: com exemplos no .Net
crescente software orientado a objetos, guiado por testes ---> Este foi realmente difícil de entender, pois JAVA não é meu idioma principal :)

Quase todos eles explicaram os conceitos básicos do TDD e os testes de unidade em geral, mas com pouca menção às diferentes maneiras pelas quais a aplicação pode ser construída.

Outra coisa que notei é que a maioria desses livros (se não todos) ignora a fase de design ao escrever o aplicativo. Eles se concentram mais em escrever os casos de teste rapidamente e deixar o design emergir por si só.

No entanto, deparei-me com um parágrafo no xUnit Test Patterns que discutia as maneiras pelas quais as pessoas abordam o TDD. Existem 2 escolas lá fora, Outside In vs Inside Out .

Infelizmente, o livro não detalha mais esse ponto. Desejo saber qual é a principal diferença entre esses dois casos.
Quando devo usar cada um deles?
Para um iniciante no TDD, qual é mais fácil de entender?
Quais são as desvantagens de cada método?
Existe algum material por aí que discuta esse tópico especificamente?

Songo
fonte
As duas abordagens são descritas no site XUnit Test Patterns: xunitpatterns.com/Philosophy%20Of%20Test%20Automation.html . É estranho que eles não estejam no livro.
precisa saber é o seguinte

Respostas:

45

Inside-Out e Outside-In são termos bastante raros, mais frequentemente eu ouvi / li sobre a escola Classic e a escola de Londres .

  • Inside-Out (escola clássica, de baixo para cima ): você começa no nível de componente / classe (dentro) e adiciona testes aos requisitos. À medida que o código evolui (devido a refatorações), novos colaboradores, interações e outros componentes aparecem. O TDD guia o projeto completamente.

  • Outside-In (escola de Londres, TDD de cima para baixo ou "mockista", como Martin Fowler o chamaria): você conhece as interações e colaboradores antecipadamente (especialmente aqueles de nível superior) e começa por lá (nível superior), zombando das dependências necessárias. Com cada componente finalizado, você passa para os colaboradores zombados anteriormente e começa com o TDD novamente lá, criando implementações reais (que, embora usadas, não eram necessárias antes graças às abstrações ). Observe que a abordagem de fora para dentro vai bem com o princípio YAGNI .

Nenhuma das abordagens é a única ; ambos têm o seu lugar, dependendo do que você faz. Em grandes soluções empresariais, onde partes do design vêm de arquitetos (ou existem antecipadamente), pode-se começar com a abordagem "ao estilo de Londres". Por outro lado, quando você enfrenta uma situação em que não tem certeza da aparência do seu código (ou de como deve se encaixar em outras partes do sistema), pode ser mais fácil começar com algum componente de baixo custo e deixá-lo evoluir à medida que mais testes, refatorações e requisitos são introduzidos.

Qualquer que seja o seu uso, mais frequentemente é situacional.

Para uma leitura mais detalhada, há uma postagem em grupo do Google com uma discussão bastante interessante sobre como essa distinção (pode ter) se originou e por que Londres pode não ser o nome mais apropriado.

km
fonte
2
Interessante. Como você chegou à conclusão de que fora do TDD é TDD "mockista"? Eu prefiro muito pensar e projetar pessoas de fora para dentro e, portanto, testar (ver softwareonastring.com/2015/01/10/… ), mas o artigo de Fowler me coloca firmemente com Fowler no campo dos classicistas. Embora o mockista possa sempre usar uma abordagem de fora para dentro, você não pode mudá-lo e dizer que o design e o teste de fora para dentro são TDD mockistas. O outside-in pode ser praticado e muito é praticado também pelos TDD-classicistas.
Marjan Venema
@jimmy_keen - Com de fora para dentro, você substitui as simulações nos testes de nível superior pelas implementações reais criadas mais tarde? Ou você as deixa como dependências simuladas e depois exercita todo o código de produção como um teste de integração?
thehowler
11
Não concordo que Classic / Mockist e Inside-Out / Outside-In estejam relacionados. Eles são ortogonais. Você pode usar Inside-Out / Outside-In com qualquer um.
Daniel Kaplan
Concordo com Daniel. Você está comparando duas taxonomias diferentes. Embora o desenvolvimento de fora para dentro seja frequentemente associado à escola (mockista) de Londres, nem sempre é o caso.
usar o seguinte
Não acho que essa seja uma descrição correta do processo de fora para dentro. Trata-se de testar a partir de interfaces públicas sem acoplamento a internos, tanto quanto possível.
precisa saber é o seguinte
15

Resposta curta: Como sempre, isso dependerá da sua preferência de codificação e da abordagem da equipe.

A codificação de dentro para fora é ótima porque você sempre tem algo funcionando. A desvantagem é que isso não ajuda necessariamente a chegar a um lugar radicalmente diferente. É mais difícil traçar um curso dessa maneira. Da mesma forma, escrever código de fora para dentro tem o lado negativo de não necessariamente ter o benefício do desenvolvimento iterativo rápido e não necessariamente de ver todas as oportunidades e padrões que podem surgir profundamente na estrutura do código.

Eu acredito que ambos os estilos de desenvolvimento são importantes e que é de fato útil ter uma mistura de estilos em uma equipe. A idéia é que de dentro para fora é ótimo para criar blocos de construção, e o pensamento de fora fornece estrutura e direção da forma.

Parte do meu raciocínio vem de uma escola de pensamento muito popular que atualmente promove o desenvolvimento iterativo, que geralmente é sinônimo de desenvolvimento de dentro para fora. Eu acredito que o desenvolvimento iterativo é ótimo quando você não tem muito longe para ir. Mas acho que esse pensamento geral, em oposição a um processo puramente iterativo, é inestimável para certos tipos de inovação e para chegar a um lugar menos óbvio. O gerenciamento adequado, de dentro para fora e de fora para dentro em conjunto pode ser uma combinação muito eficaz.

EL Yusubov
fonte
8

Você deve adicionar princípios, padrões e práticas ágeis em C # a essa lista. Não sei por que ele seguiu "em c #" no final. Os livros não são o idioma e a única razão pela qual não recebeu 5 estrelas na amazônia é de pessoas que ficaram decepcionadas com o c # -ness de seus exemplos.

O autor defende que, sempre que possível, você deve tentar escrever código de fora para dentro e confiar muito no design evolutivo, e eu concordo com a afirmação dele. Seu raciocínio é que, à medida que adicionamos funcionalidade, nosso design sempre evoluirá. Se começarmos com componentes de baixo nível à medida que os recursos forem adicionados, perceberemos que esses componentes não estão fazendo o que gostaríamos que eles fizessem, ou que as coisas precisam ser mudadas. Isso pode ficar bastante caro, especialmente se toda vez que você move a funcionalidade de uma classe para outra, é necessário fazer a mesma ação em todos os projetos de teste de unidade.

Por outro lado, se você determinar o que seu aplicativo deve fazer em primeiro lugar, codifique a interface externa. À medida que os recursos são adicionados e o código sob teste cresce em tamanho, você refatora seu aplicativo em mais classes, mas enquanto esse esforço de refatoração está em andamento, os testes de unidade originais que você escreveu permanecem válidos. Portanto, você começa completamente do lado de fora e continua refatorando em classes cada vez mais baixas, enquanto adiciona testes de unidade adicionais a essas classes internas, mas você raramente precisa se mover e reescrever seus testes de unidade.

No entanto, se você identificar um subsistema de baixo nível específico que seu aplicativo precisará (e talvez sua empresa já precise desse subsistema em outros aplicativos), seria a hora de começar primeiro com um componente básico de baixo nível e depois crie o aplicativo em cima disso.

DXM
fonte
7

A meu ver, o conceito de desenvolvimento de fora para dentro realmente se espalha em dois níveis. Gerard Meszaros os descreve brevemente como " design de fora para dentro " e " codificação de fora para dentro / dentro para fora ".

  • O primeiro nível é um nível organizacional e de processo. O design de fora para dentro é o contrário de cima para baixo (cachoeira / taylorist) e de baixo para cima. Com uma abordagem de fora para dentro, focamos na perspectiva do usuário final. Começamos com testes de história, testes ATDD ou BDD e vamos "interiormente" inferindo testes e códigos técnicos. Portanto, o design externo é o que você faria em um contexto Agile. Dan North fala muito sobre abordagens BDD, de cima para baixo, de baixo para cima e de fora para dentro.

  • O segundo nível é técnico e tem a ver com as camadas aplicáveis. A codificação de fora para dentro basicamente significa iniciar a partir da interface do usuário e avançar para a camada central (geralmente a camada de negócios / domínio). Ele se destina ao contrário da codificação de dentro para fora, que começa na camada central e codifica as camadas externas por último.

Assim, você pode ter um design de fora para dentro com a codificação de fora para dentro ou de dentro para fora.

O que eu discordo de Meszaros é quando ele associa a codificação de dentro para fora com o teste de integração, argumentando que em um contexto de dentro para fora "na verdade não testamos o software externo isoladamente do software interno". Mas acredito que nada o impede. Você pode escolher perfeitamente testar seus objetos da camada externa zombando dos objetos da camada interna, mesmo que o código de produção para eles já exista. Você só precisa adicionar interfaces e zombarias sobre os objetos concretos existentes, em vez de escrever as interfaces, zombando delas e, em seguida, criando as implementações mais tarde, como faria com a codificação de fora para dentro.

Em outras palavras, o TDD estilo mockista ou classicista é IMO uma preocupação ortogonal à codificação de fora para dentro / de dentro para fora. Você pode usar perfeitamente um estilo mockista junto com uma abordagem de dentro para fora. A razão por trás disso é que o estilo mockista / classicista é sobre dependências de código, enquanto a codificação de fora para dentro / de dentro para fora é sobre camadas de aplicativos .

Outra coisa importante é que as dependências não são apenas entre camadas, elas também existem entre objetos na mesma camada. Por exemplo, você pode começar com um objeto em sua camada central de negócios (abordagem de dentro para fora) e usar zombarias para isolar seu objeto de outros objetos da camada de negócios com os quais ele conversa. Isso acontece muito com a IoC - as abstrações de que seu objeto depende são frequentemente declaradas na mesma camada, mas implementações concretas estão em uma camada diferente.

Robert "Tio Bob" Martin menciona brevemente a codificação de dentro para fora e como ela não necessariamente entra em conflito com uma arquitetura dissociada em seu post " Arquitetura Limpa ".

guillaume31
fonte