임베디드시스템의 테스트 주도 개발: 예제코드
Table of Contents
CppUTest 예제
tests/test_add.cpp
#include "CppUTest/TestHarness.h" #include "CppUTestExt/MockSupport.h" extern "C" { #include "add.h" } #define OK 1 TEST_GROUP(Add) { static int mock_send_serial(int value) { return mock().actualCall("send_serial").withParameter("value",value).returnValue().getIntValue(); } void setup() { } void teardown() { } }; TEST(Add, simple_case) { LONGS_EQUAL(2,add(1,1)); } TEST(Add, send_added_result) { mock().expectOneCall("send_serial").withParameter("value",7).andReturnValue(OK); send_added_result(3,4); }
src/add/add.c
#include "add.h" int add(int x, int y) { return x+y; }
include/add.h
int add(int x,int y);
tests/AllTests.cpp
#include "CppUTest/CommandLineTestRunner.h" #include "CppUTest/TestPlugin.h" #include "CppUTest/TestRegistry.h" #include "CppUTestExt/MockSupportPlugin.h" int main(int ac, char** av) { MockSupportPlugin mockPlugin; TestRegistry::getCurrentRegistry()->installPlugin(&mockPlugin); return CommandLineTestRunner::RunAllTests(ac, av); } #include "AllTests.h"
tests/AllTests.h
IMPORT_TEST_GROUP(Add);
arduino 예제 프로그램
src/main.cpp
#include <WProgram.h> int ledPin = 13; // LED connected to digital pin 13 int inPin= 5; // button connected to digital pin 5 int val; void setup() { pinMode(ledPin, OUTPUT); // sets the digital pin as output pinMode(inPin, INPUT); // sets the digital pin as input Serial.begin(38400); //baud rate } void loop() { unsigned long ctime=millis(); val = digitalRead(inPin); // read the input pin digitalWrite(ledPin, val); // sets the LED to the button's value Serial.print(val, DEC); // write to the serial port as the decimal value represented as characters } int main(void) { init(); setup(); for (;;) { loop(); } }
Makefile
#Set this to @ to keep the makefile quiet SILENCE = @ #---- Outputs ----# COMPONENT_NAME = Add TARGET_LIB = \ lib/lib$(COMPONENT_NAME).a TEST_TARGET = \ $(COMPONENT_NAME)_tests #--- Inputs ----# PROJECT_HOME_DIR = . CPPUTEST_HOME = ../CppUTest CPPUTEST_USE_EXTENSIONS = Y CPP_PLATFORM = Gcc ## WARNINGFLAGS += -Wall -Wswitch-default -Wswitch-enum MEMLEAK_DETECTOR_NEW_MACROS += -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorNewMacros.h MEMLEAK_DETECTOR_MALLOC_MACROS += -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorMallocMacros.h ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N) CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED endif ifeq ($(ENABLE_DEBUG), Y) CPPUTEST_CPPFLAGS += -g endif ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N) CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED CPPUTEST_CXXFLAGS += -nostdinc++ endif CPPUTEST_CPPFLAGS += $(WARNINGFLAGS) CPPUTEST_CXXFLAGS += $(MEMLEAK_DETECTOR_NEW_MACROS) CPPUTEST_CFLAGS += $(MEMLEAK_DETECTOR_MALLOC_MACROS) ## #GCOVFLAGS = -fprofile-arcs -ftest-coverage #SRC_DIRS is a list of source directories that make up the target library #If test files are in these directories, their IMPORT_TEST_GROUPs need #to be included in main to force them to be linked in. By convention #put them into an AllTests.h file in each directory SRC_DIRS = \ src/* \ #TEST_SRC_DIRS is a list of directories including # - A test main (AllTests.cpp by conventin) # - OBJ files in these directories are included in the TEST_TARGET # - Consequently - AllTests.h containing the IMPORT_TEST_GROUPS is not needed # - TEST_SRC_DIRS = \ tests \ #includes for all compiles INCLUDE_DIRS =\ $(CPPUTEST_HOME)/include/\ include/\ mocks/\ tests/\ #Flags to pass to ld LDFLAGS += LD_LIBRARIES += -lstdc++ include $(CPPUTEST_HOME)/build/ComponentMakefile # Next: Makefile for AVR # MCU MCU = atmega168 F_CPU = 7372800L TARGET = $(COMPONENT_NAME) # AVRDUDE PORT=COM1 # TODO: Change Serial Port BAUD=19200 PROTOCOL=stk500v1 PART=m168 AVRDUDE=avrdude # Directory DIR_ARDUINO = lib/ArduinoCore CUT_INCLUDE = include DIR_SRC = src CUT_SRC = src/add # Objects OBJS = # src objs file CUT_OBJS = add.o # src/keyboard objs file CPP_OBJS = main.o # main.cpp AVR_CFLAGS = -c -g -Os -w -ffunction-sections -fdata-sections -mmcu=$(MCU) -DF_CPU=$(F_CPU) -I$(DIR_ARDUINO) -I$(CUT_INCLUDE) AVR_CPPFLAGS = -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -mmcu=$(MCU) -DF_CPU==$(F_CPU) -I$(DIR_ARDUINO) -I$(CUT_INCLUDE) -I$(DIR_SRC) RM := rm -rf # All Target upload: OBJS += $(CUT_OBJS) upload: OBJS += $(CPP_OBJS) upload: elf secondary-outputs upload: avrclean $(CUT_OBJS): %.o: $(CUT_SRC)/%.c @echo 'Compile ' avr-gcc $(AVR_CFLAGS) $< -o $@ $(OBJS): %.o: $(DIR_SRC)/%.c @echo 'Compile ' avr-gcc $(AVR_CFLAGS) $< -o $@ $(CPP_OBJS): %.o: $(DIR_SRC)/%.cpp @echo ' ' avr-g++ $(AVR_CPPFLAGS) $< -o $@ elf: $(OBJS) $(CUT_OBJS) $(CPP_OBJS) @echo 'Building target: $(TARGET)' @echo 'Invoking: AVR C++ Linker' avr-gcc -Os -Wl,--gc-sections -mmcu=$(MCU) -o $(TARGET).elf $(OBJS) $(DIR_ARDUINO)/Debug/libArduinoCore.a -L"../../ArduinoCore" -lm @echo 'Finished building target: $(TARGET)' @echo ' ' lss: @echo 'Invoking: AVR Create Extended Listing' avr-objdump -h -S $(TARGET).elf > $(TARGET).lss @echo 'Finished building: $(TARGET)' @echo ' ' hex: @echo 'Create Flash image (ihex format)' avr-objcopy -R .eeprom -O ihex $(TARGET).elf $(TARGET).hex @echo 'Finished building: $@' @echo ' ' size: @echo 'Invoking: Print Size' avr-size --format=avr --mcu=$(MCU) $(TARGET).elf @echo 'Finished building: $@' @echo ' ' avrdude: @echo 'Invoking: AVRDude' $(AVRDUDE) -p$(PART) -carduino -P$(PORT) -b$(BAUD) -F -Uflash:w:$(TARGET).hex:a @echo 'Finished building: $@' @echo ' ' avrclean: $(RM) $(OBJS)$(C_DEPS)$(ELFS) *.lss *.hex $(S_DEPS)$(CXX_DEPS)$(S_UPPER_DEPS)$(C++_DEPS)$(ASM_DEPS)$(CC_DEPS)$(CPP_DEPS)$(C_UPPER_DEPS) *.elf *.o @echo ' ' secondary-outputs: lss hex size avrdude .PHONY: upload dependents .SECONDARY:
파이썬에서 시리얼 통신
serialmonitor.py
import serial,sys print "> entered" s=serial.Serial("Com1", 38400) s.flush() print "> serial opened" def linereader(s): b=[] while True: b.append(s.read()) if b[-1]=='\n': yield ''.join(b) b=[] lr=linereader(s) try: while True: for i in lr: sys.stdout.write(i) sys.stdout.flush() finally: s.close()
read_keystep.py
import serial, sys filename = 'i.log' print "> entered" s=serial.Serial("Com1", 38400) s.flush() print "> serial opened" f=open(filename,'w') event = None value = None i=0 try: while True: event = s.read() if event not in '012': print "unexpected input: %s"%repr(event) continue e = int(event) if e == 0: event = 'NOEVT' elif e == 1: event = 'PRESSED' elif e == 2: event = 'RELEASED' if event=='PRESSED': sys.stdout.write('P') if event=='RELEASED': sys.stdout.write('R') sys.stdout.write('%03d\n'%i) i+=1 sys.stdout.flush() f.flush() finally: f.close() s.close()
파이썬으로 키보드 'a' 키 입력
import ctypes ctypes.windll.user32.keybd_event(ord("A"),0,0,0) #press ctypes.windll.user32.keybd_event(ord("A"),0,2,0) #release
Date: 2010-12-23 13:34:05