Introdução ao CppUTest
Pássaro
14 de mai. de 2017
1 min read

Principais Conclusões
CppUTest é um framework de teste leve e ativamente mantido, no estilo xUnit, para C/C++, com uma camada de integração em C que funciona perfeitamente mesmo em bases de código pesadas em C.
Você pode instalá-lo através de gerenciadores de pacotes (distribuições Linux, Homebrew) ou clonar o repositório do GitHub.
Uma configuração mínima consiste em:
um diretório de
src/de produção,um diretório de teste
t/,um executor de testes (
CommandLineTestRunner), emódulos de teste usando os blocos
TEST_GROUPeTEST().
CppUTest fornece um MakefileWorker.mk auxiliar que simplifica a construção de testes, a vinculação de bibliotecas e o tratamento de flags.
A detecção de vazamentos de memória é ativada por padrão através de sobreposições de malloc/free, capturando vazamentos dentro do código-fonte testado.
A cobertura de código via gcov integra-se facilmente habilitando
CPPUTEST_USE_GCOV=Y, produzindo relatórios de cobertura completa e resumos em HTML.O framework inclui recursos avançados: simulações, plugins, scripts auxiliares e interoperabilidade direta em C — útil para bases de código empresarial complexas.
Destaques de Perguntas e Respostas
O que é CppUTest e por que usá-lo?
É um framework de testes robusto, estilo xUnit, para C/C++ com uma API limpa, macros de assertiva embutidas, detecção de vazamentos e desenvolvimento ativo — ideal para sistemas legados ou modernos.
Como você estrutura um projeto básico usando CppUTest?
src/ code/ code.cpp code.h main.cpp t/ main.cpp (test runner) test.cpp (test suite)
Como você executa todos os testes?
O executor de testes usa:
return CommandLineTestRunner::RunAllTests(ac, av);
Como você cria testes sem configurar manualmente as opções do compilador?
Use
MakefileWorker.mkdo CppUTest, que lida automaticamente com bandeiras, vinculação e execução de testes.O CppUTest pode detectar vazamentos de memória automaticamente?
Sim. Ele substitui malloc/free durante as compilações de teste, relatando:
qual teste vazou,
onde ocorreu,
tamanho do vazamento e conteúdos da memória.
Exemplo de saída de falha:
Memory leak(s) found. Allocated at: code.c line 6 Leak size: 1
Como eu gero cobertura de código?
Habilitar:
CPPUTEST_USE_GCOV=YAssegure-se de que
filterGcov.shesteja disponível em$(CPPUTEST_HOME)/scripts/.Execute: make
gcovIsso produz
.gcov, texto resumo e relatórios de cobertura em HTML.
O que mais o CppUTest pode fazer além dos testes básicos?
framework de simulação
sistema de plugins
scripts de automação auxiliares
integração nativa com C
macros de asserção extensivas
Para quem o CppUTest é mais adequado?
Equipes trabalhando com sistemas embarcados, plataformas C, serviços C++ ou qualquer ambiente onde a confiabilidade e a segurança da memória devem ser continuamente validadas.
No SparkPost, dedicamos muito tempo e esforço para testar nosso código. Nossa plataforma é escrita em C, e recentemente pesquisei a integração com um framework de teste de unidade chamado "CppUTest", que fornece testes no estilo xUnit para C/C++. Este framework é robusto, rico em recursos e está em desenvolvimento ativo, o que o torna uma ótima escolha. Ele também fornece uma camada de integração em C, o que facilitou o uso com nosso código C da plataforma, embora a maior parte do framework seja em C++. Este tutorial aborda como começar a usar o CppUTest em seus próprios projetos.
No SparkPost, dedicamos muito tempo e esforço para testar nosso código. Nossa plataforma é escrita em C, e recentemente pesquisei a integração com um framework de teste de unidade chamado "CppUTest", que fornece testes no estilo xUnit para C/C++. Este framework é robusto, rico em recursos e está em desenvolvimento ativo, o que o torna uma ótima escolha. Ele também fornece uma camada de integração em C, o que facilitou o uso com nosso código C da plataforma, embora a maior parte do framework seja em C++. Este tutorial aborda como começar a usar o CppUTest em seus próprios projetos.
No SparkPost, dedicamos muito tempo e esforço para testar nosso código. Nossa plataforma é escrita em C, e recentemente pesquisei a integração com um framework de teste de unidade chamado "CppUTest", que fornece testes no estilo xUnit para C/C++. Este framework é robusto, rico em recursos e está em desenvolvimento ativo, o que o torna uma ótima escolha. Ele também fornece uma camada de integração em C, o que facilitou o uso com nosso código C da plataforma, embora a maior parte do framework seja em C++. Este tutorial aborda como começar a usar o CppUTest em seus próprios projetos.
Interessado em saber mais?
Este é apenas a ponta do iceberg quando se trata de todos os recursos contidos nesta ferramenta. Além dos conceitos básicos discutidos aqui, ela também possui uma estrutura de simulação, uma camada de integração direta com C e uma estrutura de plugin, para citar alguns dos mais significativos. O repositório também contém um diretório inteiro de scripts auxiliares que podem ajudar a automatizar algumas das partes rotineiras de trabalho com a estrutura.
Espero que as informações aqui ajudem você a melhorar a qualidade do seu código C/C++ com esta ótima ferramenta!
Este é apenas a ponta do iceberg quando se trata de todos os recursos contidos nesta ferramenta. Além dos conceitos básicos discutidos aqui, ela também possui uma estrutura de simulação, uma camada de integração direta com C e uma estrutura de plugin, para citar alguns dos mais significativos. O repositório também contém um diretório inteiro de scripts auxiliares que podem ajudar a automatizar algumas das partes rotineiras de trabalho com a estrutura.
Espero que as informações aqui ajudem você a melhorar a qualidade do seu código C/C++ com esta ótima ferramenta!
Este é apenas a ponta do iceberg quando se trata de todos os recursos contidos nesta ferramenta. Além dos conceitos básicos discutidos aqui, ela também possui uma estrutura de simulação, uma camada de integração direta com C e uma estrutura de plugin, para citar alguns dos mais significativos. O repositório também contém um diretório inteiro de scripts auxiliares que podem ajudar a automatizar algumas das partes rotineiras de trabalho com a estrutura.
Espero que as informações aqui ajudem você a melhorar a qualidade do seu código C/C++ com esta ótima ferramenta!
Baixando CppUTest
A página do projeto CppUTest está disponível no site oficial, e o repositório está no github. Também está incluído nos repositórios de gerenciamento de pacotes de muitas distribuições Linux, além de homebrew no Mac OS. Os exemplos a seguir foram executados no Mac OS X, mas são derivados de código escrito para Red Hat, o sistema operacional em que nossa plataforma funciona.
Os conceitos básicos estão bem documentados na página inicial do CppUTest. Vamos passar rapidamente por isso e chegar a alguns dos recursos mais interessantes.
A página do projeto CppUTest está disponível no site oficial, e o repositório está no github. Também está incluído nos repositórios de gerenciamento de pacotes de muitas distribuições Linux, além de homebrew no Mac OS. Os exemplos a seguir foram executados no Mac OS X, mas são derivados de código escrito para Red Hat, o sistema operacional em que nossa plataforma funciona.
Os conceitos básicos estão bem documentados na página inicial do CppUTest. Vamos passar rapidamente por isso e chegar a alguns dos recursos mais interessantes.
A página do projeto CppUTest está disponível no site oficial, e o repositório está no github. Também está incluído nos repositórios de gerenciamento de pacotes de muitas distribuições Linux, além de homebrew no Mac OS. Os exemplos a seguir foram executados no Mac OS X, mas são derivados de código escrito para Red Hat, o sistema operacional em que nossa plataforma funciona.
Os conceitos básicos estão bem documentados na página inicial do CppUTest. Vamos passar rapidamente por isso e chegar a alguns dos recursos mais interessantes.
Colocando a Base
Primeiro as coisas, vamos escrever algum código!
Nosso projeto de teste terá um arquivo ‘main’ e incluirá uma biblioteca utilitária chamada ‘code’. A biblioteca fornecerá uma função simples que retornará 1 (por enquanto). Os arquivos serão organizados assim:
├── src │ ├── code │ │ ├── code.cpp │ │ └── code.h │ └── main.cpp └── t ├── main.cpp └── test.cpp
Vamos começar escrevendo os arquivos src/
// src/main.cpp #include <stdlib.h> #include <stdio.h> #include "code.h" int main(void) { test_func(); printf("hello world!\n"); exit(0); }
// src/code/code.cpp #include <stdlib.h> #include "code.h" int test_func() { return 1; }
// src/code/code.h #ifndef __code_h__ #define __code_h__ int test_func(); #endif
Agora, vamos fazer os testes, que estarão no diretório t/. A primeira coisa a fazer é configurar um runner de testes que executará nossos arquivos de teste. Esta também é a função ‘main’ que será executada uma vez que tudo esteja compilado:
// t/main.cpp #include "CppUTest/CommandLineTestRunner.h" int main(int ac, char** av) { return CommandLineTestRunner::RunAllTests(ac, av); }
Agora podemos escrever nosso primeiro módulo de teste:
// t/test.cpp #include "CppUTest/TestHarness.h" #include "code.h" TEST_GROUP(AwesomeExamples) { }; TEST(AwesomeExamples, FirstExample) { int x = test_func(); CHECK_EQUAL(1, x); }
Em seguida, precisamos escrever makefiles. Precisaremos de dois: um para os arquivos do projeto sob src/, e um para os testes.
Primeiro as coisas, vamos escrever algum código!
Nosso projeto de teste terá um arquivo ‘main’ e incluirá uma biblioteca utilitária chamada ‘code’. A biblioteca fornecerá uma função simples que retornará 1 (por enquanto). Os arquivos serão organizados assim:
├── src │ ├── code │ │ ├── code.cpp │ │ └── code.h │ └── main.cpp └── t ├── main.cpp └── test.cpp
Vamos começar escrevendo os arquivos src/
// src/main.cpp #include <stdlib.h> #include <stdio.h> #include "code.h" int main(void) { test_func(); printf("hello world!\n"); exit(0); }
// src/code/code.cpp #include <stdlib.h> #include "code.h" int test_func() { return 1; }
// src/code/code.h #ifndef __code_h__ #define __code_h__ int test_func(); #endif
Agora, vamos fazer os testes, que estarão no diretório t/. A primeira coisa a fazer é configurar um runner de testes que executará nossos arquivos de teste. Esta também é a função ‘main’ que será executada uma vez que tudo esteja compilado:
// t/main.cpp #include "CppUTest/CommandLineTestRunner.h" int main(int ac, char** av) { return CommandLineTestRunner::RunAllTests(ac, av); }
Agora podemos escrever nosso primeiro módulo de teste:
// t/test.cpp #include "CppUTest/TestHarness.h" #include "code.h" TEST_GROUP(AwesomeExamples) { }; TEST(AwesomeExamples, FirstExample) { int x = test_func(); CHECK_EQUAL(1, x); }
Em seguida, precisamos escrever makefiles. Precisaremos de dois: um para os arquivos do projeto sob src/, e um para os testes.
Primeiro as coisas, vamos escrever algum código!
Nosso projeto de teste terá um arquivo ‘main’ e incluirá uma biblioteca utilitária chamada ‘code’. A biblioteca fornecerá uma função simples que retornará 1 (por enquanto). Os arquivos serão organizados assim:
├── src │ ├── code │ │ ├── code.cpp │ │ └── code.h │ └── main.cpp └── t ├── main.cpp └── test.cpp
Vamos começar escrevendo os arquivos src/
// src/main.cpp #include <stdlib.h> #include <stdio.h> #include "code.h" int main(void) { test_func(); printf("hello world!\n"); exit(0); }
// src/code/code.cpp #include <stdlib.h> #include "code.h" int test_func() { return 1; }
// src/code/code.h #ifndef __code_h__ #define __code_h__ int test_func(); #endif
Agora, vamos fazer os testes, que estarão no diretório t/. A primeira coisa a fazer é configurar um runner de testes que executará nossos arquivos de teste. Esta também é a função ‘main’ que será executada uma vez que tudo esteja compilado:
// t/main.cpp #include "CppUTest/CommandLineTestRunner.h" int main(int ac, char** av) { return CommandLineTestRunner::RunAllTests(ac, av); }
Agora podemos escrever nosso primeiro módulo de teste:
// t/test.cpp #include "CppUTest/TestHarness.h" #include "code.h" TEST_GROUP(AwesomeExamples) { }; TEST(AwesomeExamples, FirstExample) { int x = test_func(); CHECK_EQUAL(1, x); }
Em seguida, precisamos escrever makefiles. Precisaremos de dois: um para os arquivos do projeto sob src/, e um para os testes.
Makefile do Projeto
O makefile do projeto estará no mesmo nível que os diretórios ‘src’ e ‘t’ na raiz do projeto. Deve parecer assim:
# Makefile SRC_DIR = ./src CODE_DIR = $(SRC_DIR)/code OUT = example TEST_DIR = t test: make -C $(TEST_DIR) test_clean: make -C $(TEST_DIR) clean code.o: gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o main: code.o gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT) all: test main clean: test_clean rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)
Note que isso usa ‘make -C’ para os alvos de teste – o que significa que chamará ‘make’ novamente usando o makefile no diretório de teste.
Neste ponto, podemos compilar o código ‘src’ com o makefile e ver que funciona:
[]$ make main gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example []$ ./example hello world
O makefile do projeto estará no mesmo nível que os diretórios ‘src’ e ‘t’ na raiz do projeto. Deve parecer assim:
# Makefile SRC_DIR = ./src CODE_DIR = $(SRC_DIR)/code OUT = example TEST_DIR = t test: make -C $(TEST_DIR) test_clean: make -C $(TEST_DIR) clean code.o: gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o main: code.o gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT) all: test main clean: test_clean rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)
Note que isso usa ‘make -C’ para os alvos de teste – o que significa que chamará ‘make’ novamente usando o makefile no diretório de teste.
Neste ponto, podemos compilar o código ‘src’ com o makefile e ver que funciona:
[]$ make main gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example []$ ./example hello world
O makefile do projeto estará no mesmo nível que os diretórios ‘src’ e ‘t’ na raiz do projeto. Deve parecer assim:
# Makefile SRC_DIR = ./src CODE_DIR = $(SRC_DIR)/code OUT = example TEST_DIR = t test: make -C $(TEST_DIR) test_clean: make -C $(TEST_DIR) clean code.o: gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o main: code.o gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT) all: test main clean: test_clean rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)
Note que isso usa ‘make -C’ para os alvos de teste – o que significa que chamará ‘make’ novamente usando o makefile no diretório de teste.
Neste ponto, podemos compilar o código ‘src’ com o makefile e ver que funciona:
[]$ make main gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example []$ ./example hello world
Testes Makefile
Para os testes, as coisas são um pouco mais envolvidas, uma vez que precisamos carregar e integrar corretamente com a biblioteca CppUTest.
O repositório CppUTest fornece um arquivo chamado “MakefileWorker.mk”. Ele oferece muita funcionalidade que torna a compilação com o CppUTest simples. O arquivo está localizado no diretório “build” no repositório git. Para este tutorial, vamos assumir que ele foi copiado para o diretório ‘t/’. Ele pode ser usado da seguinte forma:
# we don’t want to use relative paths, so we set these variables PROJECT_DIR=/path/to/project SRC_DIR=$(PROJECT_DIR)/src TEST_DIR=$(PROJECT_DIR)/t # specify where the source code and includes are located INCLUDE_DIRS=$(SRC_DIR)/code SRC_DIRS=$(SRC_DIR)/code # specify where the test code is located TEST_SRC_DIRS=$(TEST_DIR) # what to call the test binary TEST_TARGET=example # where the cpputest library is located CPPUTEST_HOME=/usr/local # run MakefileWorker.mk with the variables defined here include MakefileWorker.mk
Note que CPPUTEST_HOME deve ser definido para onde quer que o CppUTest tenha sido instalado. Se você instalou um pacote de distribuição, isso estará tipicamente sob /usr/local em um sistema linux/mac. Se você fez o checkout do repositório por conta própria, está onde aquele checkout está.
Essas opções estão todas documentadas em MakefileWorker.mk.
MakefileWorker.mk também adiciona alguns alvos de makefile, incluindo os seguintes:
todos – compila os testes indicados pelo makefile
limpar – remove todos os arquivos objeto e gcov gerados para os testes
limpar tudo – remove qualquer arquivo objeto ou gcov em toda a árvore de diretórios
bandeiras – lista todas as bandeiras configuradas usadas para compilar os testes
depurar – lista todos os arquivos fonte, objetos, dependências e ‘coisas a limpar’
Componente | Finalidade | Arquivos Chave / Bandeiras | Notas |
|---|---|---|---|
Makefile do Projeto | Compila o código-fonte principal | Makefile de nível raiz usando make | Compila |
Makefile de Testes | Compila e vincula testes com o CppUTest |
| Gerencia compilação de teste, vinda e bandeiras de biblioteca |
MakefileWorker.mk | Fornece lógica de construção reutilizável | Localizado no diretório | Adiciona alvos: |
Integração GCov | Habilita relatórios de cobertura de código |
| Produz arquivos |
Detecção de Vazamento de Memória | Detecta vazamentos de malloc/free |
| Ativado por padrão; pode ser desativado com |
Executor de Testes | Executa grupos de testes |
| Ponto de entrada principal necessário para executar testes |
Para os testes, as coisas são um pouco mais envolvidas, uma vez que precisamos carregar e integrar corretamente com a biblioteca CppUTest.
O repositório CppUTest fornece um arquivo chamado “MakefileWorker.mk”. Ele oferece muita funcionalidade que torna a compilação com o CppUTest simples. O arquivo está localizado no diretório “build” no repositório git. Para este tutorial, vamos assumir que ele foi copiado para o diretório ‘t/’. Ele pode ser usado da seguinte forma:
# we don’t want to use relative paths, so we set these variables PROJECT_DIR=/path/to/project SRC_DIR=$(PROJECT_DIR)/src TEST_DIR=$(PROJECT_DIR)/t # specify where the source code and includes are located INCLUDE_DIRS=$(SRC_DIR)/code SRC_DIRS=$(SRC_DIR)/code # specify where the test code is located TEST_SRC_DIRS=$(TEST_DIR) # what to call the test binary TEST_TARGET=example # where the cpputest library is located CPPUTEST_HOME=/usr/local # run MakefileWorker.mk with the variables defined here include MakefileWorker.mk
Note que CPPUTEST_HOME deve ser definido para onde quer que o CppUTest tenha sido instalado. Se você instalou um pacote de distribuição, isso estará tipicamente sob /usr/local em um sistema linux/mac. Se você fez o checkout do repositório por conta própria, está onde aquele checkout está.
Essas opções estão todas documentadas em MakefileWorker.mk.
MakefileWorker.mk também adiciona alguns alvos de makefile, incluindo os seguintes:
todos – compila os testes indicados pelo makefile
limpar – remove todos os arquivos objeto e gcov gerados para os testes
limpar tudo – remove qualquer arquivo objeto ou gcov em toda a árvore de diretórios
bandeiras – lista todas as bandeiras configuradas usadas para compilar os testes
depurar – lista todos os arquivos fonte, objetos, dependências e ‘coisas a limpar’
Componente | Finalidade | Arquivos Chave / Bandeiras | Notas |
|---|---|---|---|
Makefile do Projeto | Compila o código-fonte principal | Makefile de nível raiz usando make | Compila |
Makefile de Testes | Compila e vincula testes com o CppUTest |
| Gerencia compilação de teste, vinda e bandeiras de biblioteca |
MakefileWorker.mk | Fornece lógica de construção reutilizável | Localizado no diretório | Adiciona alvos: |
Integração GCov | Habilita relatórios de cobertura de código |
| Produz arquivos |
Detecção de Vazamento de Memória | Detecta vazamentos de malloc/free |
| Ativado por padrão; pode ser desativado com |
Executor de Testes | Executa grupos de testes |
| Ponto de entrada principal necessário para executar testes |
Para os testes, as coisas são um pouco mais envolvidas, uma vez que precisamos carregar e integrar corretamente com a biblioteca CppUTest.
O repositório CppUTest fornece um arquivo chamado “MakefileWorker.mk”. Ele oferece muita funcionalidade que torna a compilação com o CppUTest simples. O arquivo está localizado no diretório “build” no repositório git. Para este tutorial, vamos assumir que ele foi copiado para o diretório ‘t/’. Ele pode ser usado da seguinte forma:
# we don’t want to use relative paths, so we set these variables PROJECT_DIR=/path/to/project SRC_DIR=$(PROJECT_DIR)/src TEST_DIR=$(PROJECT_DIR)/t # specify where the source code and includes are located INCLUDE_DIRS=$(SRC_DIR)/code SRC_DIRS=$(SRC_DIR)/code # specify where the test code is located TEST_SRC_DIRS=$(TEST_DIR) # what to call the test binary TEST_TARGET=example # where the cpputest library is located CPPUTEST_HOME=/usr/local # run MakefileWorker.mk with the variables defined here include MakefileWorker.mk
Note que CPPUTEST_HOME deve ser definido para onde quer que o CppUTest tenha sido instalado. Se você instalou um pacote de distribuição, isso estará tipicamente sob /usr/local em um sistema linux/mac. Se você fez o checkout do repositório por conta própria, está onde aquele checkout está.
Essas opções estão todas documentadas em MakefileWorker.mk.
MakefileWorker.mk também adiciona alguns alvos de makefile, incluindo os seguintes:
todos – compila os testes indicados pelo makefile
limpar – remove todos os arquivos objeto e gcov gerados para os testes
limpar tudo – remove qualquer arquivo objeto ou gcov em toda a árvore de diretórios
bandeiras – lista todas as bandeiras configuradas usadas para compilar os testes
depurar – lista todos os arquivos fonte, objetos, dependências e ‘coisas a limpar’
Componente | Finalidade | Arquivos Chave / Bandeiras | Notas |
|---|---|---|---|
Makefile do Projeto | Compila o código-fonte principal | Makefile de nível raiz usando make | Compila |
Makefile de Testes | Compila e vincula testes com o CppUTest |
| Gerencia compilação de teste, vinda e bandeiras de biblioteca |
MakefileWorker.mk | Fornece lógica de construção reutilizável | Localizado no diretório | Adiciona alvos: |
Integração GCov | Habilita relatórios de cobertura de código |
| Produz arquivos |
Detecção de Vazamento de Memória | Detecta vazamentos de malloc/free |
| Ativado por padrão; pode ser desativado com |
Executor de Testes | Executa grupos de testes |
| Ponto de entrada principal necessário para executar testes |
Cobertura de Código
Os testes de unidade não estariam completos sem um relatório de cobertura. A ferramenta ideal para isso em projetos que utilizam gcc é gcov, disponível como parte do conjunto padrão de utilitários do gcc. O Cpputest se integra facilmente ao gcov, tudo que você precisa fazer é adicionar esta linha ao arquivo Makefile:
CPPUTEST_USE_GCOV=Y
Em seguida, precisamos garantir que o script filterGcov.sh do este repositório esteja em ‘/scripts/filterGcov.sh’ em relação a onde você definiu ‘CPPUTEST_HOME’. Ele também precisa ter permissões de execução.
No exemplo de Makefile, ele seria implantado em ‘/usr/local/scripts/filterGcov.sh’. Se você estiver executando o CppUTest a partir de uma cópia do repositório, tudo deve funcionar sem modificações.
Com isso em mente, você pode simplesmente executar ‘make gcov’ e a análise será gerada para você. No nosso caso, precisaremos de ‘make -B’ para reconstruir os arquivos objeto com o gcov habilitado:
[]$ make -B gcov < compilation output > for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \ FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \ gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \ done for f in ; do \ gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \ done /usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt cat gcov_report.txt 100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp mkdir -p gcov mv *.gcov gcov mv gcov_* gcov See gcov directory for details
Isso irá gerar vários arquivos em um novo diretório ‘gcov’. Estes são:
code.cpp.gcov – o arquivo ‘gcov’ real para o código sendo testado
gcov_error.txt – um relatório de erro (no nosso caso, deve estar vazio)
gcov_output.txt – a saída real do comando gcov que foi executado
gcov_report.txt – um resumo da cobertura para cada arquivo sob teste
gcov_report.txt.html – uma versão html do gcov_report
Os testes de unidade não estariam completos sem um relatório de cobertura. A ferramenta ideal para isso em projetos que utilizam gcc é gcov, disponível como parte do conjunto padrão de utilitários do gcc. O Cpputest se integra facilmente ao gcov, tudo que você precisa fazer é adicionar esta linha ao arquivo Makefile:
CPPUTEST_USE_GCOV=Y
Em seguida, precisamos garantir que o script filterGcov.sh do este repositório esteja em ‘/scripts/filterGcov.sh’ em relação a onde você definiu ‘CPPUTEST_HOME’. Ele também precisa ter permissões de execução.
No exemplo de Makefile, ele seria implantado em ‘/usr/local/scripts/filterGcov.sh’. Se você estiver executando o CppUTest a partir de uma cópia do repositório, tudo deve funcionar sem modificações.
Com isso em mente, você pode simplesmente executar ‘make gcov’ e a análise será gerada para você. No nosso caso, precisaremos de ‘make -B’ para reconstruir os arquivos objeto com o gcov habilitado:
[]$ make -B gcov < compilation output > for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \ FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \ gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \ done for f in ; do \ gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \ done /usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt cat gcov_report.txt 100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp mkdir -p gcov mv *.gcov gcov mv gcov_* gcov See gcov directory for details
Isso irá gerar vários arquivos em um novo diretório ‘gcov’. Estes são:
code.cpp.gcov – o arquivo ‘gcov’ real para o código sendo testado
gcov_error.txt – um relatório de erro (no nosso caso, deve estar vazio)
gcov_output.txt – a saída real do comando gcov que foi executado
gcov_report.txt – um resumo da cobertura para cada arquivo sob teste
gcov_report.txt.html – uma versão html do gcov_report
Os testes de unidade não estariam completos sem um relatório de cobertura. A ferramenta ideal para isso em projetos que utilizam gcc é gcov, disponível como parte do conjunto padrão de utilitários do gcc. O Cpputest se integra facilmente ao gcov, tudo que você precisa fazer é adicionar esta linha ao arquivo Makefile:
CPPUTEST_USE_GCOV=Y
Em seguida, precisamos garantir que o script filterGcov.sh do este repositório esteja em ‘/scripts/filterGcov.sh’ em relação a onde você definiu ‘CPPUTEST_HOME’. Ele também precisa ter permissões de execução.
No exemplo de Makefile, ele seria implantado em ‘/usr/local/scripts/filterGcov.sh’. Se você estiver executando o CppUTest a partir de uma cópia do repositório, tudo deve funcionar sem modificações.
Com isso em mente, você pode simplesmente executar ‘make gcov’ e a análise será gerada para você. No nosso caso, precisaremos de ‘make -B’ para reconstruir os arquivos objeto com o gcov habilitado:
[]$ make -B gcov < compilation output > for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \ FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \ gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \ done for f in ; do \ gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \ done /usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt cat gcov_report.txt 100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp mkdir -p gcov mv *.gcov gcov mv gcov_* gcov See gcov directory for details
Isso irá gerar vários arquivos em um novo diretório ‘gcov’. Estes são:
code.cpp.gcov – o arquivo ‘gcov’ real para o código sendo testado
gcov_error.txt – um relatório de erro (no nosso caso, deve estar vazio)
gcov_output.txt – a saída real do comando gcov que foi executado
gcov_report.txt – um resumo da cobertura para cada arquivo sob teste
gcov_report.txt.html – uma versão html do gcov_report
Detecção de Vazamento de Memória do Cpputest
Cpputest permite que você detecte automaticamente a memória vazada redefinindo a família de funções padrão "malloc/free" para usar seus próprios wrappers. Isso permite que ele capture rapidamente vazamentos e os relate para cada execução de teste. Isso está habilitado por padrão em MakefileWorker.mk, então já está ativo com os passos descritos até agora.
Para ilustrar, vamos vazar um pouco de memória em test_func() !
Voltando ao código.c, adicionamos um malloc() à função, assim:
int test_func() { malloc(1); return 1; }
Agora, após recompilar, o seguinte erro é produzido:
test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample) Memory leak(s) found. Alloc num (4) Leak size: 1 Allocated at: ./code.c and line: 6 Type: "malloc" Memory: <
Isso mostra qual teste causou o vazamento, onde o vazamento aconteceu no código-fonte e o que estava na memória vazada. Muito útil!
Existem algumas ressalvas com esse recurso:
Cpputest está usando macros de pré-processamento para redefinir dinamicamente todas as chamadas às funções padrão de gerenciamento de memória. Isso significa que funcionará apenas para chamadas no código-fonte sob teste, já que é isso que é compilado com as sobreposições do CppUTest. Vazamentos em bibliotecas vinculadas não serão capturados.
Às vezes, a memória que é alocada para toda a vida do processo não deve ser liberada. Isso pode gerar muitos erros indesejados se você estiver testando um módulo com esse comportamento. Para desativar a detecção de vazamentos, você pode fazer o seguinte:
CPPUTEST_USE_MEM_LEAK_DETECTION=N
Cpputest permite que você detecte automaticamente a memória vazada redefinindo a família de funções padrão "malloc/free" para usar seus próprios wrappers. Isso permite que ele capture rapidamente vazamentos e os relate para cada execução de teste. Isso está habilitado por padrão em MakefileWorker.mk, então já está ativo com os passos descritos até agora.
Para ilustrar, vamos vazar um pouco de memória em test_func() !
Voltando ao código.c, adicionamos um malloc() à função, assim:
int test_func() { malloc(1); return 1; }
Agora, após recompilar, o seguinte erro é produzido:
test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample) Memory leak(s) found. Alloc num (4) Leak size: 1 Allocated at: ./code.c and line: 6 Type: "malloc" Memory: <
Isso mostra qual teste causou o vazamento, onde o vazamento aconteceu no código-fonte e o que estava na memória vazada. Muito útil!
Existem algumas ressalvas com esse recurso:
Cpputest está usando macros de pré-processamento para redefinir dinamicamente todas as chamadas às funções padrão de gerenciamento de memória. Isso significa que funcionará apenas para chamadas no código-fonte sob teste, já que é isso que é compilado com as sobreposições do CppUTest. Vazamentos em bibliotecas vinculadas não serão capturados.
Às vezes, a memória que é alocada para toda a vida do processo não deve ser liberada. Isso pode gerar muitos erros indesejados se você estiver testando um módulo com esse comportamento. Para desativar a detecção de vazamentos, você pode fazer o seguinte:
CPPUTEST_USE_MEM_LEAK_DETECTION=N
Cpputest permite que você detecte automaticamente a memória vazada redefinindo a família de funções padrão "malloc/free" para usar seus próprios wrappers. Isso permite que ele capture rapidamente vazamentos e os relate para cada execução de teste. Isso está habilitado por padrão em MakefileWorker.mk, então já está ativo com os passos descritos até agora.
Para ilustrar, vamos vazar um pouco de memória em test_func() !
Voltando ao código.c, adicionamos um malloc() à função, assim:
int test_func() { malloc(1); return 1; }
Agora, após recompilar, o seguinte erro é produzido:
test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample) Memory leak(s) found. Alloc num (4) Leak size: 1 Allocated at: ./code.c and line: 6 Type: "malloc" Memory: <
Isso mostra qual teste causou o vazamento, onde o vazamento aconteceu no código-fonte e o que estava na memória vazada. Muito útil!
Existem algumas ressalvas com esse recurso:
Cpputest está usando macros de pré-processamento para redefinir dinamicamente todas as chamadas às funções padrão de gerenciamento de memória. Isso significa que funcionará apenas para chamadas no código-fonte sob teste, já que é isso que é compilado com as sobreposições do CppUTest. Vazamentos em bibliotecas vinculadas não serão capturados.
Às vezes, a memória que é alocada para toda a vida do processo não deve ser liberada. Isso pode gerar muitos erros indesejados se você estiver testando um módulo com esse comportamento. Para desativar a detecção de vazamentos, você pode fazer o seguinte:
CPPUTEST_USE_MEM_LEAK_DETECTION=N



