用AI对一段代码进行单元测试

该文章已生成可运行项目,

1 题目

测试代码如下:

#include <stdio.h>

#define MIN_RUN 32

// 插入排序算法
void insertionSort(int arr[], int left, int right) {
    for (int i = left + 1; i <= right; i++) {
        int key = arr[i];
        int j = i - 1;
        while (j >= left && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

// 归并函数
void merge(int arr[], int left, int mid, int right) {
    int len1 = mid - left + 1;
    int len2 = right - mid;
    int L[len1], R[len2];

	int i = 0, j = 0, k;
    for (i = 0; i < len1; i++)
        L[i] = arr[left + i];
    for (j = 0; j < len2; j++)
        R[j] = arr[mid + 1 + j];

    i = 0;
	j = 0;
	k = left;

    while (i < len1 && j < len2) {
        if (L[i] <= R[j])
            arr[k++] = L[i++];
        else
            arr[k++] = R[j++];
    }
	
    while (i < len1)
        arr[k++] = L[i++];
    while (j < len2)
        arr[k++] = R[j++];
	while(i>j && len1<len2)
		arr[i++] = arr[j++];
}

// Timsort 算法
void timSort(int arr[], int n) {
    for (int i = 0; i < n; i += MIN_RUN)
        insertionSort(arr, i, (i + MIN_RUN - 1) < n ? (i + MIN_RUN - 1) : (n - 1));

    for (int size = MIN_RUN; size < n; size *= 2) {
        for (int left = 0; left < n; left += 2 * size) {
            int mid = left + size - 1;
            int right = (left + 2 * size - 1) < (n - 1) ? (left + 2 * size - 1) : (n - 1);
            merge(arr, left, mid, right);
        }
    }
}

利用AI工具对以上代码编写单元测试用例

2 说明

ai工具:文心大模型4.0 Turbo。
测试环境:在Linux环境下,用gcc、gcov和lcov。
测试方式:将以上代码放到sort.c文件中,用ai工具生成测试用例,放到test.c文件中,然后在Linux环境下编译运行,测试是否所有测试用例可以通过,用lcov生成html格式的测试报告。

3 操作过程

3.1 用AI优化需求

首先编写一个让ai生成单元测试代码的需求,然后发给ai让其优化一下。
输入

对这段代码编写单元测试案例,实现100%语句覆盖、判定覆盖、条件覆盖(CC)、条件/判定覆盖(C/DC)、条件组合覆盖(MCC)、修正判定条件覆盖(MCDC)。 
要求: 
1、验证结果是否正确,不用预期结果与输出结果对比的方式,用遍历输出结果,判断是否前一个数据比后一个小 
2、打印出哪些测试用例通过了,哪些测试用例没通过,生成一个结果测试报告。
3、除了生成一些常规的测试数据,再生成一些超长的,里面是随机数的输入数组,数组长度一个是500,一个是1000 
4、生成一些长度不同的输入数组,长度从100连续到299,共200组,里面都是随机数 
5、每个测试用例封装成一个函数。
6、对于第3条和第4条要求的测试用例,打印测试结果时要标明测试数组长度。
7、用malloc申请内存存放输入数据时,测试完要及时释放。
9、常规测试数据里类型多一些,都是一些容易测试出代码问题的数据。
10、测试代码和被测试代码不在同一个文件中,被测试代码已经写好不需要ai再写一遍,只需要生成测试代码

以上是一个我要输入给文心一言的需求,现在对这个需求进行优化,让文心一言输出效果更好

输出

为了优化您的需求描述,使其更清晰、具体,并引导生成更高质量的测试代码,以下是对原始需求的优化版本:
________________________________________
测试代码生成需求优化版
目标:
为给定的排序函数编写单元测试,确保实现100%的语句覆盖、判定覆盖、条件覆盖(CC)、条件/判定覆盖(C/DC)、条件组合覆盖(MCC)、修正判定条件覆盖(MCDC)。
具体要求:
1.	验证方法:
	不通过预期结果与输出结果对比,而是通过遍历输出结果,判断数组是否已排序(即前一个数据是否比后一个小)。
2.	测试报告:
	打印出哪些测试用例通过了,哪些没通过。
	生成一个详细的测试报告,包括测试用例名称和测试结果。
3.	测试用例生成:
	常规测试数据:
	包含多种类型的数据,如空数组、单元素数组、已排序数组、逆序数组、含重复元素的数组、特殊值数组(如最大/最小值、负数、零等)。
	这些数据应易于触发代码中的潜在问题。
	超长随机数组:
	生成两个长度分别为500和1000的随机数组。
	打印测试结果时标明测试数组长度。
	连续长度随机数组:
	生成长度从100到299的200组随机数组。
	每组数组长度连续递增,打印测试结果时标明测试数组长度。
4.	测试用例封装:
	每个测试用例应封装成一个独立的函数,便于管理和复用。
5.	内存管理:
	使用malloc申请内存存放输入数据时,测试完成后要及时释放内存,避免内存泄漏。
6.	测试代码与被测试代码分离:
	假设被测试代码已经写好,只需编写测试代码。
	测试代码应位于与被测试代码不同的文件中。
优化后的详细步骤:
1.	编写测试框架:
	创建一个测试框架,能够执行测试用例并记录结果。
	提供函数用于打印测试报告。
2.	实现测试用例:
	常规测试用例:
	空数组测试。
	单元素数组测试。
	已排序数组测试。
	逆序数组测试。
	含重复元素的数组测试。
	特殊值数组测试(如全为正数、全为负数、混合正负数、含零等)。
	超长随机数组测试用例:
	生成并测试长度为500和1000的随机数组。
	连续长度随机数组测试用例:
	生成并测试长度从100到299的200组随机数组。
3.	验证排序结果:
	在每个测试用例中,遍历排序后的数组,检查是否满足排序条件(前一个元素小于或等于后一个元素)。
4.	内存管理:
	确保在每个测试用例中,使用malloc分配的内存都在测试完成后被正确释放。
5.	生成测试报告:
	在所有测试用例执行完毕后,生成并打印详细的测试报告,包括每个测试用例的名称、测试结果(通过/失败)以及任何额外的信息(如数组长度)。
期望输出:
•	一个清晰的测试报告,显示所有测试用例的执行结果。
•	对于失败的测试用例,应提供足够的信息以便定位问题。
________________________________________
通过优化后的需求描述,您可以更清晰地指导文心一言生成高质量的测试代码,确保覆盖所有必要的测试场景,并生成详细的测试报告。

3.2 用AI生成单元测试代码

将被测试代码和需求发给AI,让其生成相应的单元测试代码。
输入

#include <stdio.h>

#define MIN_RUN 32

// 插入排序算法
void insertionSort(int arr[], int left, int right) {
    for (int i = left + 1; i <= right; i++) {
        int key = arr[i];
        int j = i - 1;
        while (j >= left && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

// 归并函数
void merge(int arr[], int left, int mid, int right) {
    int len1 = mid - left + 1;
    int len2 = right - mid;
    int L[len1], R[len2];

	int i = 0, j = 0, k;
    for (i = 0; i < len1; i++)
        L[i] = arr[left + i];
    for (j = 0; j < len2; j++)
        R[j] = arr[mid + 1 + j];

    i = 0;
	j = 0;
	k = left;

    while (i < len1 && j < len2) {
        if (L[i] <= R[j])
            arr[k++] = L[i++];
        else
            arr[k++] = R[j++];
    }
	
    while (i < len1)
        arr[k++] = L[i++];
    while (j < len2)
        arr[k++] = R[j++];
	while(i>j && len1<len2)
		arr[i++] = arr[j++];
}

// Timsort 算法
void timSort(int arr[], int n) {
    for (int i = 0; i < n; i += MIN_RUN)
        insertionSort(arr, i, (i + MIN_RUN - 1) < n ? (i + MIN_RUN - 1) : (n - 1));

    for (int size = MIN_RUN; size < n; size *= 2) {
        for (int left = 0; left < n; left += 2 * size) {
            int mid = left + size - 1;
            int right = (left + 2 * size - 1) < (n - 1) ? (left + 2 * size - 1) : (n - 1);
            merge(arr, left, mid, right);
        }
    }
}

测试代码生成需求优化版

目标:
为给定的排序函数编写单元测试,确保实现100%的语句覆盖、判定覆盖、条件覆盖(CC)、条件/判定覆盖(C/DC)、条件组合覆盖(MCC)、修正判定条件覆盖(MCDC)。

具体要求:

验证方法:
不通过预期结果与输出结果对比,而是通过遍历输出结果,判断数组是否已排序(即前一个数据是否比后一个小)。
测试报告:
打印出哪些测试用例通过了,哪些没通过。
生成一个详细的测试报告,包括测试用例名称和测试结果。
测试用例生成:
常规测试数据:
包含多种类型的数据,如空数组、单元素数组、已排序数组、逆序数组、含重复元素的数组、特殊值数组(如最大/最小值、负数、零等)。
这些数据应易于触发代码中的潜在问题。
超长随机数组:
生成两个长度分别为500和1000的随机数组。
打印测试结果时标明测试数组长度。
连续长度随机数组:
生成长度从100到299的200组随机数组。
每组数组长度连续递增,打印测试结果时标明测试数组长度。
测试用例封装:
每个测试用例应封装成一个独立的函数,便于管理和复用。
内存管理:
使用malloc申请内存存放输入数据时,测试完成后要及时释放内存,避免内存泄漏。
测试代码与被测试代码分离:
假设被测试代码已经写好,只需编写测试代码。
测试代码应位于与被测试代码不同的文件中。
优化后的详细步骤:

编写测试框架:
创建一个测试框架,能够执行测试用例并记录结果。
提供函数用于打印测试报告。
实现测试用例:
常规测试用例:
空数组测试。
单元素数组测试。
已排序数组测试。
逆序数组测试。
含重复元素的数组测试。
特殊值数组测试(如全为正数、全为负数、混合正负数、含零等)。
超长随机数组测试用例:
生成并测试长度为500和1000的随机数组。
连续长度随机数组测试用例:
生成并测试长度从100到299的200组随机数组。
验证排序结果:
在每个测试用例中,遍历排序后的数组,检查是否满足排序条件(前一个元素小于或等于后一个元素)。
内存管理:
确保在每个测试用例中,使用malloc分配的内存都在测试完成后被正确释放。
生成测试报告:
在所有测试用例执行完毕后,生成并打印详细的测试报告,包括每个测试用例的名称、测试结果(通过/失败)以及任何额外的信息(如数组长度)。
期望输出:

一个清晰的测试报告,显示所有测试用例的执行结果。
对于失败的测试用例,应提供足够的信息以便定位问题。

输出

为了实现你要求的测试框架和测试用例,我们将创建一个新的C文件来包含测试代码,并确保与被测试代码(即timSort函数)分离。以下是详细的实现步骤:
1. 测试框架
首先,我们创建一个测试框架,能够执行测试用例并记录结果。
c复制代码
	#include <stdio.h>
	#include <stdlib.h>
	#include <stdbool.h>
	#include <time.h>
	
	// 假设 timSort 函数声明在这里(通常通过包含头文件)
	extern void timSort(int arr[], int n);
	
	// 检查数组是否已排序
	bool isSorted(int arr[], int n) {
	for (int i = 0; i < n - 1; i++) {
	if (arr[i] > arr[i + 1]) {
	return false;
	}
	}
	return true;
	}
	
	// 打印测试报告
	void printTestReport(const char* testName, bool result, int length = -1) {
	if (length == -1) {
	printf("Test Case: %s - %s\n", testName, result ? "Passed" : "Failed");
	} else {
	printf("Test Case: %s (Length: %d) - %s\n", testName, length, result ? "Passed" : "Failed");
	}
	}
	
	// 测试用例模板
	void runTestCase(const char* testName, int* arr, int n) {
	timSort(arr, n);
	bool result = isSorted(arr, n);
	printTestReport(testName, result, n);
	// 释放内存(如果适用)
	// 注意:在这个框架中,假设传入数组不是动态分配的,因此不需要释放
	}
2. 实现测试用例
接下来,我们实现具体的测试用例。
c复制代码
	void testEmptyArray() {
	int arr[0];
	runTestCase("Empty Array", arr, 0);
	}
	
	void testSingleElementArray() {
	int arr[1] = {1};
	runTestCase("Single Element Array", arr, 1);
	}
	
	void testSortedArray() {
	int arr[] = {1, 2, 3, 4, 5};
	runTestCase("Sorted Array", arr, 5);
	}
	
	void testReverseSortedArray() {
	int arr[] = {5, 4, 3, 2, 1};
	runTestCase("Reverse Sorted Array", arr, 5);
	}
	
	void testArrayWithDuplicates() {
	int arr[] = {3, 3, 3, 2, 2, 1, 1};
	runTestCase("Array With Duplicates", arr, 7);
	}
	
	void testSpecialValuesArray() {
	int arr[] = {INT_MAX, INT_MIN, 0, -1, 1, 99999, -99999};
	runTestCase("Special Values Array", arr, 7);
	}
	
	void testLongRandomArray(int length) {
	int* arr = (int*)malloc(length * sizeof(int));
	if (arr == NULL) {
	printf("Memory allocation failed for length %d\n", length);
	return;
	}
	
	// 填充随机数
	srand(time(NULL));
	for (int i = 0; i < length; i++) {
	arr[i] = rand() % 100000 - 50000; // 随机数范围 [-50000, 49999]
	}
	
	runTestCase("Long Random Array", arr, length);
	
	// 释放内存
	free(arr);
	}
	
	void testSequentialLengthRandomArrays() {
	for (int length = 100; length < 300; length++) {
	testLongRandomArray(length);
	}
	}
	
	int main() {
	// 运行常规测试用例
	testEmptyArray();
	testSingleElementArray();
	testSortedArray();
	testReverseSortedArray();
	testArrayWithDuplicates();
	testSpecialValuesArray();
	
	// 运行超长随机数组测试用例
	testLongRandomArray(500);
	testLongRandomArray(1000);
	
	// 运行连续长度随机数组测试用例
	testSequentialLengthRandomArrays();
	
	return 0;
	}
3. 解释与注意事项
•	测试框架:runTestCase函数用于执行排序并检查结果,同时打印测试报告。
•	测试用例:每个测试用例都是一个独立的函数,便于管理和复用。
•	内存管理:在testLongRandomArray中,使用malloc分配内存,并在测试完成后使用free释放内存。
•	随机数组生成:使用rand函数生成随机数,并用srand(time(NULL))确保每次运行产生不同的随机数序列。
•	测试报告:printTestReport函数用于打印每个测试用例的结果,包括名称、是否通过以及数组长度(如果适用)。
这个测试框架和测试用例覆盖了多种可能的输入情况,确保了较高的代码覆盖率,并能够帮助定位潜在的问题。

3.3 搭建测试环境

将ai生成的代码放到test.c中,并做一些优化。内容如下:

#define MIN_RUN 32

#define INT_MAX 2147483647
#define INT_MIN -2147483648

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
 
// 假设 timSort 函数声明在这里(通常通过包含头文件)
extern void timSort(int arr[], int n);
 
// 检查数组是否已排序
bool isSorted(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        if (arr[i] > arr[i + 1]) {
            return false;
        }
    }
    return true;
}
 
// 打印测试报告
void printTestReport(const char* testName, bool result, int length) {
    if (length == -1) {
        printf("Test Case: %s - %s\n", testName, result ? "Passed" : "Failed");
    } else {
        printf("Test Case: %s (Length: %d) - %s\n", testName, length, result ? "Passed" : "Failed");
    }
}
 
// 测试用例模板
void runTestCase(const char* testName, int* arr, int n) {
    timSort(arr, n);
    bool result = isSorted(arr, n);
    printTestReport(testName, result, n);
    // 释放内存(如果适用)
    // 注意:在这个框架中,假设传入数组不是动态分配的,因此不需要释放
}

void testEmptyArray() {
    int arr[0];
    runTestCase("Empty Array", arr, 0);
}
 
void testSingleElementArray() {
    int arr[1] = {1};
    runTestCase("Single Element Array", arr, 1);
}
 
void testSortedArray() {
    int arr[] = {1, 2, 3, 4, 5};
    runTestCase("Sorted Array", arr, 5);
}
 
void testReverseSortedArray() {
    int arr[] = {5, 4, 3, 2, 1};
    runTestCase("Reverse Sorted Array", arr, 5);
}
 
void testArrayWithDuplicates() {
    int arr[] = {3, 3, 3, 2, 2, 1, 1};
    runTestCase("Array With Duplicates", arr, 7);
}
 
void testSpecialValuesArray() {
    int arr[] = {INT_MAX, INT_MIN, 0, -1, 1, 99999, -99999};
    runTestCase("Special Values Array", arr, 7);
}
 
void testLongRandomArray(int length) {
    int* arr = (int*)malloc(length * sizeof(int));
    if (arr == NULL) {
        printf("Memory allocation failed for length %d\n", length);
        return;
    }
    
    // 填充随机数
    srand(time(NULL));
    for (int i = 0; i < length; i++) {
        arr[i] = rand() % 100000 - 50000; // 随机数范围 [-50000, 49999]
    }
    
    runTestCase("Long Random Array", arr, length);
    
    // 释放内存
    free(arr);
}
 
void testSequentialLengthRandomArrays() {
    for (int length = 100; length < 300; length++) {
        testLongRandomArray(length);
    }
}
 
int main() {
    // 运行常规测试用例
    testEmptyArray();
    testSingleElementArray();
    testSortedArray();
    testReverseSortedArray();
    testArrayWithDuplicates();
    testSpecialValuesArray();
    
    // 运行超长随机数组测试用例
    testLongRandomArray(500);
    testLongRandomArray(1000);
    
    // 运行连续长度随机数组测试用例
    testSequentialLengthRandomArrays();
    
    return 0;
}

将被测试代码放到sort.c中,编写一个脚本用于编译生成可执行文件,然后运行并生成测试覆盖率报告。测试目录内容如下:
在这里插入图片描述
其中test.sh的内容如下:
在这里插入图片描述
sort.c是被测试代码。

3.4 第1次测试

运行test.sh脚本,生成的测试报告如下:
在这里插入图片描述
从测试报告可以看出,在处理长度为129的数组时,程序运行发生的错误,在sort.c文件中加一些打印信息用于调试,添加过程如下:
在这里插入图片描述
然后只测试长度129的数组,运行结果如下:
在这里插入图片描述
可以看到出错原因是因为运行到这里时,mid比right的值大,而merge函数内容如下:
在这里插入图片描述
当mid大于right时,len2的计算结果为负数,这使得声明数组R时出现错误。所以当mid大于right时,表示不能分成两段进行合并,因此就不需要合并。根据以上分析优化代码如下:
在这里插入图片描述
再一次测试,测试用例全部通过。

3.5 第2次测试

在分析第一个问题时发现,merge函数中声明L数组和R数组的方式有些问题,代码如下:
在这里插入图片描述
这种方式声明的L数组和R数组存放在栈空间,栈空间相对较小,当输入的排序数组过大时,可能会出现内存溢出。为了验证是否会出现内存溢出,增加一个100M的输入数组用来测试。修改test.c内容如下:
在这里插入图片描述
用修改完的test.c文件进一步测试,发现果然在处理100M大数组时出现程序运行错误,如下:
在这里插入图片描述
根据以上分析,决定将L和R用malloc的方式申请内存,使其数据存放到内存较大的堆空间,修改代码如下:
在这里插入图片描述
然后再一次测试发现测试用例全部通过,测试结果如下:

在这里插入图片描述
在这里插入图片描述
这时查看代码运行覆盖率报告,结果如下:

在这里插入图片描述
可以看到其中有一段代码没有被运行到。

3.5 第3次测试

以上所写操作方式并不是第一次就是这么做的,经历过多次的迭代,初期让ai生成测试代码时,并没有附加多条要求,这时ai生成的测试代码总是有几条无法覆盖。将覆盖率报告反馈给ai让其优化测试代码时,ai指出来一段错误代码,如下:
在这里插入图片描述
原始代码如下:

在这里插入图片描述
前经过前面的代码处理后,这时应该i=len1、j=len2,所以不会出现(i>j && len1<len2)的情况。而且前面步骤已经将数据处理完毕,所以45行、46行是错误的代码行。
将错误代码删除,修改如下:

在这里插入图片描述
用修改之后的代码再测试,此时测试用例全部通过,并且代码运行覆盖率为100%,结果如下:
在这里插入图片描述
在这里插入图片描述

本文章已经生成可运行项目
<think>我们使用AI生成C#单元测试通常有两种方式: 1. 利用AI代码生成工具(如GitHub Copilot、ChatGPT等)根据代码描述生成测试用例。 2. 使用测试框架(如NUnit、xUnit、MSTest)结合AI生成测试代码。 步骤: a. 提供待测试的C#代码AI工具。 b. 指定测试框架(如NUnit)。 c. AI根据代码逻辑生成测试用例(包括正常情况、边界情况、异常情况)。 示例:假设我们有一个C#类 `Calculator`,其中包含一个 `Add` 方法。 待测试代码: ```csharp public class Calculator { public int Add(int a, int b) { return a + b; } } ``` 我们可以要求AI生成基于NUnit的测试类: 生成的测试代码可能如下: ```csharp using NUnit.Framework; [TestFixture] public class CalculatorTests { [Test] public void Add_TwoPositiveNumbers_ReturnsSum() { // Arrange Calculator calculator = new Calculator(); // Act int result = calculator.Add(3, 5); // Assert Assert.AreEqual(8, result); } [Test] public void Add_PositiveAndNegativeNumber_ReturnsSum() { Calculator calculator = new Calculator(); int result = calculator.Add(10, -5); Assert.AreEqual(5, result); } [Test] public void Add_TwoNegativeNumbers_ReturnsSum() { Calculator calculator = new Calculator(); int result = calculator.Add(-7, -3); Assert.AreEqual(-10, result); } [Test] public void Add_Zero_ReturnsOtherNumber() { Calculator calculator = new Calculator(); int result = calculator.Add(0, 15); Assert.AreEqual(15, result); result = calculator.Add(20, 0); Assert.AreEqual(20, result); } } ``` 解释: - `[TestFixture]` 表示这是一个包含测试的类。 - `[Test]` 标记一个测试方法。 - 每个测试方法遵循AAA模式(Arrange, Act, Assert): - Arrange:设置测试环境(创建对象等)。 - Act:执行待测试的方法。 - Assert:验证结果是否符合预期。 使用AI生成单元测试的注意事项: 1. 确保覆盖所有分支:包括正常情况、边界情况(如最大值、最小值)、异常情况(如果方法可能抛出异常)。 2. 对于更复杂的方法,AI可能需要更多上下文来生成有效的测试用例。 3. 生成的测试代码可能需要人工调整,特别是当方法依赖外部资源(如数据库、网络)时,需要模拟(Mock)这些依赖。 进阶:如果方法有异常抛出,例如除法方法中除数为0: ```csharp public int Divide(int a, int b) { if (b == 0) throw new DivideByZeroException(); return a / b; } ``` 则测试代码应该包含对异常的测试: ```csharp [Test] public void Divide_DivisorIsZero_ThrowsDivideByZeroException() { Calculator calculator = new Calculator(); Assert.Throws<DivideByZeroException>(() => calculator.Divide(10, 0)); } ``` 使用AI生成单元测试可以大大提高效率,但需要人工审查以确保测试的准确性和完整性。 §§相关问题§§: 1. 如何使用AI生成带有模拟(Mock)的单元测试(例如使用Moq框架)? 2. AI如何帮助生成针对数据库操作的单元测试? 3. 如何利用AI生成C#中异步方法的单元测试? 4. 除了NUnit,AI如何生成基于xUnit或MSTest的测试代码?</think>### 如何使用 AI 生成 C# 单元测试 以下是使用 AI 生成 C# 单元测试的完整解决方案,使用 NUnit 测试框架作为示例: #### 解决方案步骤: 1. **提供待测试代码**:向 AI 描述需要测试的 C# 方法或类 2. **指定测试框架**:明确要求使用 NUnit/xUnit/MSTest 3. **描述测试场景**:包括正常情况、边界情况和异常情况 4. **生成测试代码**:AI 输出完整的测试类和测试方法 #### 示例:为 C# 计算器类生成单元测试 **待测试代码**: ```csharp public class Calculator { public int Add(int a, int b) => a + b; public double Divide(int dividend, int divisor) { if (divisor == 0) throw new DivideByZeroException(); return (double)dividend / divisor; } } ``` **AI 生成的 NUnit 测试代码**: ```csharp using NUnit.Framework; [TestFixture] public class CalculatorTests { private Calculator _calculator; [SetUp] public void Setup() { _calculator = new Calculator(); } // 测试正常加法 [Test] public void Add_TwoPositiveNumbers_ReturnsSum() { // Arrange int a = 5, b = 3; // Act int result = _calculator.Add(a, b); // Assert Assert.AreEqual(8, result); } // 测试边界加法 [Test] public void Add_MaxIntValues_ReturnsCorrectSum() { int result = _calculator.Add(int.MaxValue, int.MaxValue); Assert.AreEqual(-2, result); // 整数溢出预期结果 } // 测试正常除法 [Test] public void Divide_TwoNumbers_ReturnsQuotient() { double result = _calculator.Divide(10, 2); Assert.AreEqual(5.0, result); } // 测试除零异常 [Test] public void Divide_ByZero_ThrowsDivideByZeroException() { // 使用 Assert.Throws 验证异常 Assert.Throws<DivideByZeroException>(() => _calculator.Divide(10, 0)); } // 参数化测试示例 [TestCase(10, 2, 5.0)] [TestCase(9, 3, 3.0)] [TestCase(7, 2, 3.5)] public void Divide_WithVariousInputs_ReturnsCorrectResult( int dividend, int divisor, double expected) { double result = _calculator.Divide(dividend, divisor); Assert.AreEqual(expected, result, 0.001); // 允许小数误差 } } ``` ### 代码解释: 1. **测试结构**: - `[TestFixture]`:标记测试类 - `[SetUp]`:每个测试前的初始化方法 - `[Test]`:标记单个测试方法 - `[TestCase]`:参数化测试,多组数据测试同一逻辑 2. **AAA 模式**: - **Arrange**:设置测试环境(初始化对象、准备数据) - **Act**:执行待测试的方法 - **Assert**:验证结果是否符合预期 3. **关键断言方法**: - `Assert.AreEqual`:验证值相等 - `Assert.Throws`:验证是否抛出特定异常 - `Assert.That`:更灵活的条件验证(NUnit 特有) 4. **测试覆盖场景**: - 正常功能验证 - 边界条件测试(如最大值) - 异常情况处理 - 多组数据验证(参数化测试) ### 进阶技巧: 1. **使用模拟框架**:当测试方法依赖外部服务时,AI 可以生成使用 Moq 的测试代码: ```csharp [Test] public void ProcessData_WithValidInput_CallsLogger() { // Arrange var mockLogger = new Mock<ILogger>(); var processor = new DataProcessor(mockLogger.Object); // Act processor.ProcessData("test"); // Assert mockLogger.Verify(logger => logger.Log(It.IsAny<string>()), Times.Once); } ``` 2. **测试异步方法**: ```csharp [Test] public async Task GetDataAsync_ReturnsValidData() { var service = new DataService(); var result = await service.GetDataAsync(); Assert.IsNotNull(result); } ``` 3. **代码覆盖率分析**: AI 可以建议使用工具如: - Coverlet:收集代码覆盖率 - ReportGenerator:生成可视化报告 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值