Blame programming-guidelines/pt_BR/unit-testing.page

Packit 1470ea
Packit 1470ea
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="unit-testing" xml:lang="pt-BR">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
    <link type="guide" xref="index#general-guidelines"/>
Packit 1470ea
Packit 1470ea
    <credit type="author copyright">
Packit 1470ea
      <name>Philip Withnall</name>
Packit 1470ea
      <email its:translate="no">philip.withnall@collabora.co.uk</email>
Packit 1470ea
      <years>2015</years>
Packit 1470ea
    </credit>
Packit 1470ea
Packit 1470ea
    <include xmlns="http://www.w3.org/2001/XInclude" href="cc-by-sa-3-0.xml"/>
Packit 1470ea
Packit 1470ea
    <desc>Projete software para ser testado e escreva testes de unidades para ele</desc>
Packit 1470ea
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Rafael Fontenelle</mal:name>
Packit 1470ea
      <mal:email>rafaelff@gnome.org</mal:email>
Packit 1470ea
      <mal:years>2017</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
  <title>Teste de unidade</title>
Packit 1470ea
Packit 1470ea
  <synopsis>
Packit 1470ea
    <title>Resumo</title>
Packit 1470ea
Packit 1470ea
    

Teste de unidade deve ser o método principal para testar o conjunto de código escrito porque um teste de unidade pode ser escrito uma vez e executado muitas outras — testes manuais têm que ser planejados uma vez e, então, executado manualmente cada vez.

Packit 1470ea
Packit 1470ea
    

O desenvolvimento de testes de unidade se inicia com o design de API e arquitetura do código a ser testado: o código deve ser projetado para ser facilmente testável, do contrário provavelmente ele será muito difícil de testar.

Packit 1470ea
Packit 1470ea
    <list>
Packit 1470ea
      <item>

Escreva testes de unidade para serem tão pequenos quanto possível, mas não menores. (<link xref="#writing-unit-tests"/>)

</item>
Packit 1470ea
      <item>

Use ferramentas de cobertura de código para escrever testes para obter alta cobertura de código. (<link xref="#writing-unit-tests"/>)

</item>
Packit 1470ea
      <item>

Execute todos os testes de unidade sob Valgrind para verificar ocorrências vazamentos e outros problemas. (<link xref="#leak-checking"/>)

</item>
Packit 1470ea
      <item>

Use as ferramentas apropriadas para automaticamente gerar testes de unidade onde for possível. (<link xref="#test-generation"/>)

</item>
Packit 1470ea
      <item>

Projete o código para ser testável desde o início. (<link xref="#writing-testable-code"/>)

</item>
Packit 1470ea
    </list>
Packit 1470ea
  </synopsis>
Packit 1470ea
Packit 1470ea
  <section id="writing-unit-tests">
Packit 1470ea
    <title>Escrevendo testes de unidade</title>
Packit 1470ea
Packit 1470ea
    

Testes de unidade devem ser escritos em conjunto com a análise das <link xref="tooling#gcov-and-lcov">informações de cobertura de código obtidas por executar os testes</link>. Geralmente isso significa escrever um conjunto inicial de testes de unidade, executando-os para obter dados de cobertura e, então, retrabalhar e expandi-los para aumentar os níveis de cobertura de código. A cobertura deve primeiro ser aumentada se certificando de que todas as funções estejam cobertas (pelo menos em parte) e, então, se certificando de que todas as linhas de código estejam cobertas. Ao cobrir as funções primeiro, problemas de API que vão evitar testes efetivos serão localizados rapidamente. Essas geralmente se manifestam como funções internas que não podem ser facilmente chamadas a partir de testes de unidade. Em geral, deve-se ter como meta os níveis de cobertura em cerca de 90%; não teste apenas os casos cobertos pelos requerimentos do projeto, teste tudo.

Packit 1470ea
Packit 1470ea
    

Assim como <link xref="version-control">git commits</link>, os testes de unidade devem ser “tão pequenos quanto possível, mas não menores”, testando especificamente uma única API ou um único comportamento. Cada caso de teste deve ser capaz de executar individualmente, sem depender do estado de outros casos de teste. Isso é importante para permitir depuração de falha em um teste, sem ter que também passar por todos os outros códigos de teste. Isso significa que a falha de um teste pode ser facilmente rastreada a uma API específica, em vez de uma mensagem genérica “testes de unidade falharam em algum lugar”.

Packit 1470ea
Packit 1470ea
    

O GLib oferece suporte a testes de unidade com seu <link href="https://developer.gnome.org/glib/stable/glib-Testing.html">framework GTest</link>, permitindo que os testes sejam organizados em grupos e hierarquias. Isso significa que os grupos de testes relacionados podem ser executados juntos para melhorar a depuração também, executando o binário de teste com o argumento <cmd>-p</cmd>: <cmd>./test-suite-nome -p /caminho/para/grupo/de/teste</cmd>.

Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="installed-tests">
Packit 1470ea
    <title>Testes instalados</title>
Packit 1470ea
Packit 1470ea
    

Todos os testes de unidade devem ser instalados para todo o sistema, seguindo o <link href="https://wiki.gnome.org/Initiatives/GnomeGoals/InstalledTests">padrão de testes instalados</link>.

Packit 1470ea
Packit 1470ea
    

Ao instalar os testes de unidade, integração contínua (CI) é facilitada, já que os testes para um projeto podem ser reexecutados após alterações em outros projetos no ambiente de CI, de forma a testar as interfaces entre módulos. Isso é útil para um conjunto altamente encaixado de projetos como o GNOME.

Packit 1470ea
Packit 1470ea
    

Para adicionar suporte para testes instalados, adicione o seguinte ao <file>configure.ac</file>:

Packit 1470ea
    # Testes instalados
Packit 1470ea
AC_ARG_ENABLE([modular_tests],
Packit 1470ea
              AS_HELP_STRING([--disable-modular-tests],
Packit 1470ea
                             [Disable build of test programs (default: no)]),,
Packit 1470ea
              [enable_modular_tests=yes])
Packit 1470ea
AC_ARG_ENABLE([installed_tests],
Packit 1470ea
              AS_HELP_STRING([--enable-installed-tests],
Packit 1470ea
                             [Install test programs (default: no)]),,
Packit 1470ea
              [enable_installed_tests=no])
Packit 1470ea
AM_CONDITIONAL([BUILD_MODULAR_TESTS],
Packit 1470ea
               [test "$enable_modular_tests" = "yes" ||
Packit 1470ea
                test "$enable_installed_tests" = "yes"])
Packit 1470ea
AM_CONDITIONAL([BUILDOPT_INSTALL_TESTS],[test "$enable_installed_tests" = "yes"])
Packit 1470ea
Packit 1470ea
    

Então, em <file>tests/Makefile.am</file>:

Packit 1470ea
    insttestdir = $(libexecdir)/installed-tests/[project]
Packit 1470ea
Packit 1470ea
all_test_programs = \
Packit 1470ea
	test-program1 \
Packit 1470ea
	test-program2 \
Packit 1470ea
	test-program3 \
Packit 1470ea
	$(NULL)
Packit 1470ea
if BUILD_MODULAR_TESTS
Packit 1470ea
TESTS = $(all_test_programs)
Packit 1470ea
noinst_PROGRAMS = $(TESTS)
Packit 1470ea
endif
Packit 1470ea
Packit 1470ea
if BUILDOPT_INSTALL_TESTS
Packit 1470ea
insttest_PROGRAMS = $(all_test_programs)
Packit 1470ea
Packit 1470ea
testmetadir = $(datadir)/installed-tests/[project]
Packit 1470ea
testmeta_DATA = $(all_test_programs:=.test)
Packit 1470ea
Packit 1470ea
testdatadir = $(insttestdir)
Packit 1470ea
testdata_DATA = $(test_files)
Packit 1470ea
Packit 1470ea
testdata_SCRIPTS = $(test_script_files)
Packit 1470ea
endif
Packit 1470ea
Packit 1470ea
EXTRA_DIST = $(test_files)
Packit 1470ea
Packit 1470ea
%.test: % Makefile
Packit 1470ea
	$(AM_V_GEN) (echo '[Test]' > $@.tmp; \
Packit 1470ea
	echo 'Type=session' >> $@.tmp; \
Packit 1470ea
	echo 'Exec=$(insttestdir)/$<' >> $@.tmp; \
Packit 1470ea
	mv $@.tmp $@)
Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="leak-checking">
Packit 1470ea
    <title>Verificação de vazamento</title>
Packit 1470ea
Packit 1470ea
    

Assim que os testes de unidade com alta cobertura de código forem escritos, eles podem ser executados sob várias ferramentas de análise dinâmica, tal como <link xref="tooling#valgrind">Valgrind</link> para verificar por vazamentos, erros de threading, problemas de alocação, etc. por toda a base de código. Quanto maior a cobertura de código dos testes unitários, mais confiança haverá nos resultados do Valgrind. Veja <link xref="tooling"/> para mais informações, incluindo instruções sobre integração de sistema de compilação.

Packit 1470ea
Packit 1470ea
    

Mais importante de tudo é que isso significa que os testes de unidade não devem eles mesmos resultar em vazamento de memória ou de outros recursos e, de forma similar, não devem ter qualquer problemas de threading. Qualquer um desses problemas seria efetivamente um falso positivo na análise do código projeto. (Falsos positivos que precisam ser resolvidos corrigindo os testes de unidade.)

Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="test-generation">
Packit 1470ea
    <title>Geração de testes</title>
Packit 1470ea
Packit 1470ea
    

Certos tipos de códigos são bem repetitivos e exigem muitos testes de unidade para obter uma boa cobertura de código; mas são apropriados para <link href="http://en.wikipedia.org/wiki/Test_data_generation">geração de dados de teste</link>, na qual uma ferramenta é usada para automaticamente gerar vetores de teste para o código. Isso pode reduzir drasticamente o tempo necessário para escrever testes de unidade, para código nesses domínio em específico.

Packit 1470ea
Packit 1470ea
    <section id="json">
Packit 1470ea
      <title>JSON</title>
Packit 1470ea
Packit 1470ea
      

Um exemplo de um domínio acessível para geração de dados de teste é análise, na qual exige-se que os dados a serem analisados sigam um esquema estrito — esse é o caso para documentos XML e JSON. Para JSON, uma ferramenta como <link href="http://people.collabora.com/~pwith/walbottle/">Walbottle</link> pode ser usado para gerar vetores de teste para todos tipos de entrada válida e inválida de acordo com o esquema.

Packit 1470ea
Packit 1470ea
      

Todo tipo de documento JSON deve ter um <link href="http://json-schema.org/">JSON Schema</link> definido para ele, que pode então ser passado para Walbottle para gerar vetores de teste:

Packit 1470ea
      
Packit 1470ea
json-schema-generate --valid-only schema.json
Packit 1470ea
json-schema-generate --invalid-only schema.json
Packit 1470ea
Packit 1470ea
      

Esses vetores de teste podem, então, ser passados para o código sob teste em seus testes de unidade. As instâncias JSON geradas por <cmd>--valid-only</cmd> deve ser aceita; aqueles de <cmd>--invalid-only</cmd> deve ser rejeitado.

Packit 1470ea
    </section>
Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="writing-testable-code">
Packit 1470ea
    <title>Escrevendo código testável</title>
Packit 1470ea
Packit 1470ea
    

O código deve ser escrito com testabilidade em mente desde o estágio de design, já que isso afeta o design de API e arquitetura em formas fundamentais. Alguns princípios chaves:

Packit 1470ea
    <list>
Packit 1470ea
      <item>

Não use um estado global. Objetos “sigleton” são geralmente uma má ideia, pois eles não podem ser instanciados separadamente ou controlados nos testes de unidade.

</item>
Packit 1470ea
      <item>

Separe o uso de estado externo, tal como banco de dados, conectividade ou sistema de arquivos. Os testes de unidade podem, então, substituir os acessos a estado externo com objetos simulados (mock). Uma abordagem comum a isso é usar injeção de dependência para passar um objeto interfaceador de sistema de arquivos para o código sob teste. Por exemplo, uma classe não deve carregar um banco de dados global (de uma localização fixa no sistema de arquivos) porque os testes de unidade poderiam acabar sobrescrevendo a cópia do sistema em execução do banco de dados, e nunca poderia ser executado em paralelo. A eles deve ser passado um objeto que fornece uma interface para o banco de dados: em um sistema de produção, isso seria um interfaceador magro em volta da API de banco de dados; para teste, seria um objeto simulado que verifica as requisições fornecidas a ele e retorna respostas codificadas para vários testes.

</item>
Packit 1470ea
      <item>

Exponha funções utilitárias onde geralmente elas podem ser úteis.

</item>
Packit 1470ea
      <item>

Divida projetos em coleções de bibliotecas pequenas e privadas, que são então vinculadas com uma quantidade mínima de código colante no executável global.

</item>
Packit 1470ea
    </list>
Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="external-links">
Packit 1470ea
    <title>Links externos</title>
Packit 1470ea
Packit 1470ea
    

O tópico de estabilidade de API é coberto nos seguintes artigos (em inglês):

Packit 1470ea
    <list>
Packit 1470ea
      <item>

<link href="http://msdn.microsoft.com/en-us/magazine/dd263069.aspx">Design por testabilidade</link>

</item>
Packit 1470ea
      <item>

<link href="http://en.wikipedia.org/wiki/Software_testability">testabilidade de software</link>

</item>
Packit 1470ea
      <item>

<link href="http://en.wikipedia.org/wiki/Dependency_injection">Injeção de dependência</link>

</item>
Packit 1470ea
      <item>

<link href="http://c2.com/cgi/wiki?SoftwareDesignForTesting">Design de software para teste</link>

</item>
Packit 1470ea
    </list>
Packit 1470ea
  </section>
Packit 1470ea
</page>