Unity單元測試初篇

前言

昨天被師兄問起程序單元測試的問題, 頓時一臉懵逼, 啥? 單元測試. 折騰了一天, 用Unity好歹擼出來一個HelloWorld級別的LED單元測試, 下面記錄下過程, 感覺好久不寫博客了, 竟有種無法下筆的感覺, 還是從這篇慢慢拾起來吧.

STM32CubeMX

先用STM32CubeMX 5.6.1建一個工程:

  • MCU選擇: 打開 STM32CubeMX, 點擊 ACCESS TO MCU SELECTOR, 選擇 STM32F767VITx

  • 調試端口配置爲SWD: Pinout & Configuration -> System Core -> SYS -> Debug 選擇 Serial Wire

  • Pinout & Configuration -> System Core -> RCC -> HSE 選擇 Crystal/Ceramic Resonator(外部用的25M晶振)

  • Clock Configuration:
    在這裏插入圖片描述

  • 配置LED(PD12接LED, 低電平點亮): 單擊PD12引腳, 設爲GPIO_Output, 然後右鍵PD12, 選擇Enter User Label, 輸入LEDR:
    在這裏插入圖片描述

  • 配置串口(Unity測試結果可以通過串口打印出來, 這裏用USART3): Pinout & Configuration -> Connectivity -> USART3, Mode選擇Asynchronous, 波特率默認115200, 引腳我挪到了板子上對應的PD8,PD9:
    在這裏插入圖片描述

  • Project Manager -> Project -> Browse 選擇工程位置(Project Location), 填入工程名(Project Name), Toolchain/IDE 選擇 MDK-ARM.
    在這裏插入圖片描述
    Project Manager -> Code Generator -> 勾選Copy only the necessary library files, 還有Generate peripheral initialization as a pair of .c/.h files per periphral
    在這裏插入圖片描述

  • 點擊右上角 GENERATE CODE 按鈕生成代碼, 打開工程.

  • Keil 點擊魔術棒或者Project -> Options for Target ..., 默認配置DebugST-link Debugger, 點擊Setting -> Flash Download -> 勾選Reset and Run, 點擊Pack去掉Enable(聽說是新版Keil的鍋?) 這樣下載後可以自動復位運行.
    在這裏插入圖片描述
    在這裏插入圖片描述

添加功能代碼

gpio.c的最下面添加led_on()和led_off()兩個函數:

/* USER CODE BEGIN 2 */
GPIO_PinState led_on(void)
{
	HAL_GPIO_WritePin(LEDR_GPIO_Port, LEDR_Pin, GPIO_PIN_RESET);
	return HAL_GPIO_ReadPin(LEDR_GPIO_Port, LEDR_Pin);
}

GPIO_PinState led_off(void)
{
	HAL_GPIO_WritePin(LEDR_GPIO_Port, LEDR_Pin, GPIO_PIN_SET);
	return HAL_GPIO_ReadPin(LEDR_GPIO_Port, LEDR_Pin);
}
/* USER CODE END 2 */

gpio.h聲明一下:

/* USER CODE BEGIN Prototypes */
extern GPIO_PinState led_on(void);
extern GPIO_PinState led_off(void);
/* USER CODE END Prototypes */

爲了支持printf, 直接在usart.c的最下面添加串口的重定向:

/* USER CODE BEGIN 1 */
#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF);

  return ch;
}
/* USER CODE END 1 */

在main.h添加頭文件:

/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "gpio.h"
/* USER CODE END Includes */

在main.c的while(1)裏面先測試一下:

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		led_on();
		HAL_Delay(1000);
		led_off();
		HAL_Delay(300);
		printf("hahage\r\n");
  }
  /* USER CODE END 3 */

編譯下載, 發現LED閃爍狀態正確, 串口115200-8-N-1打印正常.

加入Unity單元測試

這裏僅以測試上面的led_on()和led_off()兩個函數爲例. (爲什麼都看到燈亮了還測試, 咳咳, 人艱不拆…).

Unity Github把master下載下來, 可以git clone https://github.com/ThrowTheSwitch/Unity.git, 也可以直接下載zip包:
在這裏插入圖片描述
拷貝從GitHub上拉下來的以下幾個文件到上面STM32工程的 /Drivers/Unity(新建的)文件夾裏:

  • Unity/src/unity.c
  • Unity/src/unity.h
  • Unity/src/unity_internals.h
  • Unity/src/unity_config.h

打開Keil工程, 點擊工程管理按鈕, 新添Target: UnitTest, 並點擊Set as Current Target按鈕, 新添Groups: Drivers/Unity, 然後點擊Add Files按鈕, 把/Drivers/Unity目錄下的unity.c添加進來:
在這裏插入圖片描述
魔術棒這裏還是要再配置一下的:
在這裏插入圖片描述
接下來把頭文件路徑包含進來:
在這裏插入圖片描述
Drivers/Unity Group添加新文件main1.c, 把main.c的所有內容拷貝到main1.c, 然後main.c右鍵:
在這裏插入圖片描述
去掉Include in Target Build勾選, 這樣UnitTest這個Target就不會編譯main.c這個文件了:
在這裏插入圖片描述

Drivers/Unity Group添加新文件test_gpio.c, 添加以下內容:

#include "gpio.h"
#include "unity.h"

void setUp(void)
{
}

void tearDown(void)
{
}

void test_led_on(void)
{
	TEST_ASSERT_EQUAL(GPIO_PIN_RESET, led_on());
	TEST_ASSERT_EQUAL(GPIO_PIN_RESET, led_on());
}

void test_led_off(void)
{
	TEST_ASSERT_EQUAL(GPIO_PIN_SET, led_off());
	TEST_ASSERT_EQUAL(GPIO_PIN_SET, led_off());
}

整個工程的目錄看下來是這樣的:
在這裏插入圖片描述

main1.c添加:

/* USER CODE BEGIN Includes */
#include "unity.h"
/* USER CODE END Includes */

/* USER CODE BEGIN 0 */
extern void setUp(void);
extern void tearDown(void);
extern void test_led_on(void);
extern void test_led_off(void);

/*=======Test Reset Option=====*/
void resetTest(void);
void resetTest(void)
{
  tearDown();
  setUp();
}
/* USER CODE END 0 */

  /* USER CODE BEGIN 2 */
	
	UnityBegin("Unit Testing");
	RUN_TEST(test_led_on, __LINE__);
	RUN_TEST(test_led_off, __LINE__);
	
  /* USER CODE END 2 */

打開unity_internals.h, 添加#define UNITY_INCLUDE_CONFIG_H, 表示我們要修改並使用unity_config.h文件:

#define UNITY_INCLUDE_CONFIG_H

#ifdef UNITY_INCLUDE_CONFIG_H
#include "unity_config.h"
#endif

打開unity_config.h文件, 添加以下配置以適配Cortext-M7, 以及測試信息的打印(通過配置的串口):

#define UNITY_EXCLUDE_LIMITS_H
#define UNITY_EXCLUDE_STDINT_H
#define UNITY_INT_WIDTH 32
#define UNITY_POINTER_WIDTH 32
#define UNITY_INCLUDE_FLOAT
#define UNITY_INCLUDE_DOUBLE

#include "main.h"
#include <stdio.h>
#ifdef __GNUC__
 #define UNITY_OUTPUT_CHAR(a)       __io_putchar(a)
#else     
 #define UnityPutc(a)            fputc(a,stdout);
 #define UNITY_OUTPUT_CHAR(a)       UnityPutc(a) 
#endif

編譯下載運行, 可以在串口調試助手中看到測試通過的信息:
在這裏插入圖片描述
如果不通過會顯示:

Unit Testing:103:test_led_on:PASS
Unit Testing:20:test_led_off:FAIL: Expected 1 Was 0

表示led_off()函數測試失敗.

工程鏈接

https://download.csdn.net/download/weifengdq/12439854

微信公衆號

歡迎掃描二維碼關注本人微信公衆號, 及時獲取或者發送給我最新消息:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章