Test Driven Development – Unity + Microchip PIC

Unity

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
TDD Unity Microchip PIC

Referências

https://github.com/ThrowTheSwitch/CeedlingExample_Microchip

Imagem destacada: FreeDigitalPhotos.net

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
1 Comentário
recentes
antigos mais votados
Inline Feedbacks
View all comments
Matheus Quick
Matheus Quick
12/03/2017 17:45

ótimo artigo

Home » Software » Engenharia de Software » Test Driven Development – Unity + Microchip PIC

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: