Atualmente exitem diversas metodologias para o desenvolvimento de software de alto nível para computadores pessoais. Algumas dessas metodologias estão sendo adaptadas para realidade de sistemas embarcados, como por exemplo, o desenvolvimento orientado a testes (TDD – Test Driven Development). Diferentemente da abordagem convencional onde todo o código é desenvolvido e apenas depois os testes (e a busca por bugs) são realizados, nesta metodologia o código é desenvolvido de forma incremental juntamente com a rotina de testes. As principais vantagens são:
- Sistema tende ser melhor projetado, melhorando-se a qualidade do código;
- Ao final do projeto, o código já foi exercitado por uma bateria de testes;
- A cada alteração no código fonte, refazer os testes é trivial;
- Evita-se a pressão de realizar testes/debug o mais rápido possível ao final do projeto;
- Entre vários outros.
Para facilitar o trabalho do desenvolvedor, existem vários frameworks para testes unitários em C, dentre eles o Unity. Basicamente o Unity é um conjunto de macros e funções que possibilitam o desenvolvedor automatizar testes unitários. Como não cobriremos neste post como funciona o Unity, deixamos como referência o livro Test Driven Development for Embedded C de James Grenning. Além do Unity, este livro é uma introdução à metodologia TDD e também mostra vários exemplos de como escrever os códigos de testes.
Vamos criar um pequeno projeto para mostrar como configurar e como o TDD pode ser usado com microcontroladores Microchip, no caso o PIC24FJ256GA106. Usaremos uma ferramenta chamada ceedling que gera automaticamente todo o ambiente necessário para se usar o Unity. Lembrando apenas que o exemplo é em uma máquina com Linux e o IDE usado para o projeto com o PIC é o MPLAB x IDE. (Veja os links de referência para saber como instalar o ceedling, como configurar em ambiente Windows e vários exemplos práticos).
1) Dentro da pasta de projetos do mplabx (geralmente o nome da pasta termina com .X), crie um projeto novo com o ceedling.
ceedling new teste_unitario
2) Dentro desta pasta, encontra-se o arquivo de configuração do projeto. Para o nosso exemplo, iremos adaptar ele para usar o compilador microchip xc16-gcc e seu simulador sim30. O arquivo de configuração deve ficar assim:
:project:
:use_exceptions: FALSE
:use_test_preprocessor: FALSE
:use_auxiliary_dependencies: TRUE
:build_root: build
:test_file_prefix: test_
:extension:
:executable: .out
:paths:
:include:
- /opt/microchip/xc16/v1.11/support/PIC24F/h
- /opt/microchip/xc16/v1.11/include/
:test:
- +:test/**
- -:test/support
:source:
- ../**
:support:
- test/support
:defines:
# in order to add common defines:
# 1) remove the trailing [] from the :common: section
# 2) add entries to the :common: section (e.g. :test: has TEST defined)
:commmon: &common_defines
- __PIC24FJ256GA106__
#- UNITY_EXCLUDE_STDINT_H
- UNITY_INT_WIDTH=16
- CMOCK_MEM_INDEX_TYPE=uint16_t
- CMOCK_MEM_PTR_AS_INT=uint16_t
- CMOCK_MEM_ALIGN=1
- CMOCK_MEM_SIZE=4096
:test:
- *common_defines
:test_preprocess:
- *common_defines
:cmock:
:mock_prefix: mock_
:when_no_prototypes: :warn
:enforce_strict_ordering: TRUE
:plugins:
- :ignore
- :callback
- :array
:treat_as:
uint8: HEX8
uint16: HEX16
uint32: UINT32
int8: INT8
bool: UINT8
:when_ptr:
- :smart
#:tools:
# Ceedling defaults to using gcc for compiling, linking, etc.
# As [:tools] is blank, gcc will be used (so long as it's in your system path)
# See documentation to configure a given toolchain for use
:tools:
:test_compiler:
:executable: xc16-gcc
:arguments:
- -mcpu=24FJ256GA106
- -x c
- -c
- -g
- -omf=elf
- "${1}"
- -o "${2}"
- -D$: COLLECTION_DEFINES_TEST_AND_VENDOR
- -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR
- -I"./"
- -Wall
- -mlarge-code
- -mlarge-data
- -mlarge-scalar
- -mconst-in-code
- -msmart-io=1
- -msfr-warn=off
:test_linker:
:executable: xc16-gcc
:arguments:
- -mcpu=24FJ256GA106
- -omf=elf
- ${1}
- -o "./build/test.out"
- -Wl,-Tp24FJ256GA106.gld,-Map=./build/test.map,--report-mem
:test_fixture:
:executable: ruby
:name: "Microchip simulator test fixture"
:stderr_redirect: :UNIX #inform Ceedling what model of $stderr capture to use
:arguments:
- test/simulation/sim_test_fixture.rb
:release_compiler:
:executable: xc16-gcc
:arguments:
- -x c
- -c
- -g
- -omf=elf
- "${1}"
- -o "${2}"
- -mcpu=24FJ256GA106
- -Wall
- -Werror
- -Os
- -mlarge-code
- -mlarge-arrays
- -mlarge-data
- -mlarge-scalar
- -mconst-in-code
- -msmart-io=1
- -msfr-warn=off
- -I"$": COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR
- -I"$": COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE
- -D$: COLLECTION_DEFINES_RELEASE_AND_VENDOR
:release_linker:
:executable: xc16-gcc
:arguments:
- -mcpu=24FJ256GA106
- ${1}
- -o "${2}"
- -omf=elf
- -Wl,--defsym=__MPLAB_BUILD=1,,--script="p24FJ256GA106.gld",--check-sections,--data-init,--pack-data,--handles,--isr,--no-gc-sections,--fill-uper=0,--stackguard=16,--no-force-link,--smart-io,--report-mem
:plugins:
:load_paths:
- vendor/ceedling/plugins
:enabled:
- stdout_pretty_tests_report
- module_generator
...
Nota1: Adicione o path do compilador no PATH do sistema.
Nota2: Nesta máquina o compilador está instalado em /opt/microchip/xc16/v1.11, e no arquivo de configuração as bibliotecas padrões são configuradas na seção:
:paths:
:include:
- /opt/microchip/xc16/v1.11/support/PIC24F/h
- /opt/microchip/xc16/v1.11/include/
3) Dentro da pasta teste_unitario/test, crie uma pasta chamada simulation:
cd test mkdir simulation
4) Em teste_unitario/test/simulation crie um arquivo chamado sim_instructions.txt e edite-o desta forma:
LD pic24super LC ./build/test.out IO NULL ./test/simulation/out.txt RP E quit
5) Em teste_unitario/test/simulation crie um arquivo chamado sim_test_fixture.rb e edite-o desta forma:
OUT_FILE = "./test/simulation/out.txt"
File.delete OUT_FILE if File.exists? OUT_FILE
IO.popen("sim30 ./test/simulation/sim_instructions.txt")
sleep 1
if File.exists? OUT_FILE
file_contents = File.read OUT_FILE
file_contents.gsub!("\n", "")
print file_contents
end
6) Adicione o código de testes em teste_unitario/test. Vale lembrar que podemos configurar o path do código fonte tanto do projeto como dos testes para apontar em qualquer outro diretório. Para isso, altere o arquivo do projeto na seção :paths:source e :path:test respectivamente.
7) Para rodar todos os testes digite:
rake test:all
ou então para rodar um teste em específico, digite rake test:test_<nome_do_teste>. No nosso caso, o teste chama-se “misc”:
rake test:test_misc
Referências
Imagem destacada: FreeDigitalPhotos.net











ótimo artigo