大家好,我是Edison。

本篇我们基于上一篇的基础,来写一个单元测试助手的prompt,让它帮我们写一些我们.NET开发者不太愿意编写的单元测试代码,进而提高我们的代码质量,同时还降低我们的开发工作量。

单元测试助手

这里我们基于上一篇中提到的万能语言辅助专家的提示词,稍作修改,形成我们的单元测试助手的提示词,如下所示,经过一些测试在GPT4-o模型下效果真的不错,建议收藏!

初始回复:“
**Hi I'm Unit Test Master,Created by Edison Zhou,V1.0,20230701**
### ⚙️ Preferences:
- lang: <> else C#
- ⏲️ test: <> else xUnit
- mock: <> else Moq
### Menu:
请使用表格输出支持的`instructions`和对应名称,不需要解释具体含义,也不需要显示这句话:
---
请指出你的开发语言,E.g.:/lang C#。
回复1保持默认。
” `preferences`
/lang:<开发语言偏好,默认为C#>
/test:<测试框架偏好,默认为xUnit>
/mock:<模拟框架偏好,默认为Moq> `instructions`
/models:被测试代码涉及到的模型定义
用户输入一些被测试代码涉及到的Models如Entity,DTO, VO等,请按以下模版输出Models相关信息:
## Models:
用表格输出:**Model Name**
/constants:被测试代码涉及到的常量或枚举定义
用户输入一些被测试代码涉及到的Constants如Enum,Constant等,请按以下模版输出Constants相关信息:
## Constants:
用表格输出:**Constant Name**
/refer: 被测试代码依赖的的对象接口定义
用户输入一些被测试代码涉及到的对象接口如Repository,Gateway等,请按以下模版输出References相关信息:
## Refers:
用表格输出:**Reference Name**
/method:被测试方法的实际代码
结合之前的models,constants,refers定义,直接生成被测试方法的单元测试,无需再用表格输出相关信息。如果还有其他要求,用户会补充告诉你。
/help:输出支持的指令指引 `rules`
- 请使用用户设置的偏好的开发语言、测试框架和模拟框架实现
- 每个单元测试方法的命名请遵循格式:"被测试方法名_测试场景_预期结果"
- 假如被测试方法中有try-catch,请考虑针对catch部分也编写单元测试用例
- 请一步一步思考,不需要解释代码,如果有错误,用户会纠正你

对话示例

假设我们有一个基于.NET开发的API项目,想要对其中某个Service的某个方法写写单元测试,我们只需要按照以下步骤即可生成可能会“一把过”的单元测试代码。

在我们的实践中,最好通过VS Code将上述的人设prompt编辑好,同时把下面需要喂给GPT的代码片段也准备好。

第一轮:偏好选择

直接回复1,即保持C#+xUnit+Moq的框架组合,默认偏好设置

第二轮:给GPT喂Models相关class的定义

例如下所示,如果model有继承一些接口或基类,最好也一起告诉GPT。

/models
public class AppTokenVo: VoBase, IVo
{
public string TokenName { get; set; }
public AppNamesapce Namespace { get; set; }
public AppTokenType Type { get; set; }
public string Remark { get; set; }
public DateTime ExpireTime { get; set; }
}
public class VoBase : IIdentity<Guid>
{
public virtual Guid Id { get; set; }
}
public class AppTokenEntity : EntityBase, IEntity
{
......
}
......

第三轮:给GPT喂Constants相关class/enum的定义

例如下所示,如果constant有继承一些接口或基类,最好也一起告诉GPT。

/constants
public enum AppStatusCode
{
......
//// +++++++++++++++++++++++++++++++++++++
//// Common error codes [-1..-99]
//// +++++++++++++++++++++++++++++++++++++
UnexpectedException = -1,
OperationFinishedWithErrors = -2,
ValidationFailed = -3,
CouldNotSaveEntityInDb = -4,
EntityNotFoundInDb = -5,
EntityAlreadyExistInDb = -6
}
......

第四轮:给GPT喂被测试方法依赖的一些对象的定义,如Repository或Gateway等

例如下所示,如果被依赖的对象有继承一些接口或基类,最好也一起告诉GPT。

/refers
public interface IOperationResult<out T> where T : class
{
int StatusCode { get; } string ErrorMessage { get; } T Content { get; } bool HasContent { get; } bool IsSuccess { get; }
}
public interface IAppTokenRepository : IEfCoreRepositoryBase<AppTokenEntity>
{
}
public interface IEfCoreRepositoryBase<TEntity> where TEntity : EntityBase, IEntity
{
Task<IEnumerable<TEntity>> GetAllAsync(Expression<Func<TEntity, bool>> predicate, bool asNoTracking = true); Task<TEntity> GetAsync(Guid id, bool asNoTracking = false); Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate, bool asNoTracking = false); Task<PagedEntityResult<TEntity>> GetPagedDataAsync(Expression<Func<TEntity, bool>> predicate, int limit, int skip); Task<PagedEntityResult<TEntity>> GetPagedDataAsync(Expression<Func<TEntity, bool>> predicate, string orderField, bool orderByAsc, int limit, int skip); TEntity Add(TEntity entity); TEntity Update(TEntity entity); TEntity Delete(TEntity entity);
}

第四轮:告诉GPT被测试的方法代码

例如下所示,最好将该service的定义和构造函数也一起告诉GPT,可以将该service的其他方法移除掉再告诉GPT,让其保持专注。

当然,这也是我们为什么需要通过编辑器将其编辑好,再统一发给GPT的原因。

/method
public class AppTokenService : AppServiceBase<AppTokenService>, IAppTokenService
{
public AppTokenService(
IAppUnitOfWork unitOfWork,
IMapper mapper,
ILogger<AppTokenService> logger)
: base(unitOfWork, mapper, logger)
{
} public async Task<IOperationResult<IEnumerable<AppTokenVo>>> GetAllAppTokensAsync()
{
Logger.LogInformation(LoggingConstants.FunctionCalled,
nameof(AppTokenService), nameof(GetAllAppTokensAsync));
try
{
......
return OperationResult<IEnumerable<AppTokenVo>>.Success(appTokens);
}
catch (Exception ex)
{
Logger.LogError(ex, LoggingConstants.Exception,
nameof(AppTokenService), nameof(GetAllAppTokensAsync));
return OperationResult<IEnumerable<AppTokenVo>>.Error((int)AppStatusCode.UnexpectedException);
}
finally
{
Logger.LogInformation(LoggingConstants.FunctionFinished,
nameof(AppTokenService), nameof(GetAllAppTokensAsync));
}
}
}

随后,GPT就会输出一些高质量的单元测试代码,你可以将其复制出来做一些验证:

(1)首先看看有没有编译错误,如果有,那一定是GPT虚构了某些依赖对象的接口定义,换言之,你忘记告诉GPT准确的定义了,因此你需要补充告诉GPT。

(2)其次如果没有编译错误了,那么恭喜你,你基本可以得到一个全部Pass的结果。但是,请再次review一下它的Assert有没有满足你的需求,如果没有,请一定反馈给GPT,按照你的需求做一些完善。

(3)最后建议跑一下代码覆盖率,看看还有没有没有覆盖的分支语句和代码行,然后反馈给GPT,直到满足你的需求再结束,比如Line Coverage和Branch Coverage都达到了80%及以上。

最后,你可能会发现你这么准备下来,可能自己手写单元测试也差不多写完了,但是这毕竟是你第一次调教GPT帮你写单元测试,当你熟悉这个套路之后,有了自己的固定模板,以后的单元测试就会越来越快,而且你几乎不需要写一行代码了,是不是很酷?

小结

本篇,我们了解了如何基于ChatGPT中的参数化表达沟通,实现一个可以帮我们开发者编写单元测试代码的单元测试助手。当然,这个Prompt我们的参数化设置,我们还可以将其用于C#之外的其他编程语言和测试框架,只要你愿意,你可以根据本文中的模板去修改和完善。

本文工具

本文示例大模型版本:gpt4-o

作者:周旭龙

出处:https://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

ChatGPT学习之旅 (8) 单元测试助手的更多相关文章

  1. Spring学习之旅(十)--MockMvc

    在之前的 Spring学习之旅(八)--SpringMVC请求参数 我们是通过在控制台输出来验证参数是否正确,但是这样做实在是太耗时间了,我们今天来学习下 MockMvc,它可以让我们不需要启动项目就 ...

  2. WCF学习之旅—第三个示例之四(三十)

           上接WCF学习之旅—第三个示例之一(二十七)               WCF学习之旅—第三个示例之二(二十八)              WCF学习之旅—第三个示例之三(二十九)   ...

  3. Hadoop学习之旅二:HDFS

    本文基于Hadoop1.X 概述 分布式文件系统主要用来解决如下几个问题: 读写大文件 加速运算 对于某些体积巨大的文件,比如其大小超过了计算机文件系统所能存放的最大限制或者是其大小甚至超过了计算机整 ...

  4. WCF学习之旅—第三个示例之二(二十八)

    上接WCF学习之旅—第三个示例之一(二十七) 五.在项目BookMgr.Model创建实体类数据 第一步,安装Entity Framework 1)  使用NuGet下载最新版的Entity Fram ...

  5. WCF学习之旅—第三个示例之三(二十九)

    上接WCF学习之旅—第三个示例之一(二十七) WCF学习之旅—第三个示例之二(二十八) 在上一篇文章中我们创建了实体对象与接口协定,在这一篇文章中我们来学习如何创建WCF的服务端代码.具体步骤见下面. ...

  6. WCF学习之旅—WCF服务部署到IIS7.5(九)

    上接   WCF学习之旅—WCF寄宿前的准备(八) 四.WCF服务部署到IIS7.5 我们把WCF寄宿在IIS之上,在IIS中宿主一个服务的主要优点是在发生客户端请求时宿主进程会被自动启动,并且你可以 ...

  7. WCF学习之旅—WCF服务部署到应用程序(十)

    上接  WCF学习之旅—WCF寄宿前的准备(八) WCF学习之旅—WCF服务部署到IIS7.5(九) 五.控制台应用程序宿主 (1) 在解决方案下新建控制台输出项目 ConsoleHosting.如下 ...

  8. WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) 七 WCF服务的Windows 服务程序寄宿 这种方式的服务寄宿,和IIS一样有一个一样 ...

  9. WCF学习之旅—WCF服务的WAS寄宿(十二)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一) 八.WAS宿主 IIS ...

  10. WCF学习之旅—WCF服务的批量寄宿(十三)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一) WCF学习之旅—WCF ...

随机推荐

  1. 配置vscode的vue环境变量

    参考下面连接: vscode中使用beautify插件格式化vue文件(自定义快捷键) https://blog.csdn.net/jiandan1127/article/details/859589 ...

  2. TeamViewer 9 和 10 即将停用 尝试切换到 Splashtop

    TeamViewer 9 和 TeamViewer 10 将于2021 年 6 月 1 日到期停用.当这两个版本的 TeamViewer 到期时,用户将无法再远程访问其计算机和设备. 这意味着要继续使 ...

  3. JDK源码阅读-------自学笔记(十八)(java.lang.Enum枚举类)

    枚举类简介 如果有必要定义一组常量的时候使用 所有的枚举类型隐性地继承自 java.lang.Enum,枚举实质上还是类. 每一个枚举中的成员,就相当于枚举的一个对象,默认都是public stati ...

  4. PageOffice 在线打开 word 文件并添加水印

    一.服务器端方法插入水印 1.插入文字水印 WordDocument doc = new WordDocument(); //添加水印 ,设置水印的内容 doc.getWaterMark().setT ...

  5. ASP.NET Core Web中使用AutoMapper进行对象映射

    前言 在日常开发中,我们常常需要将一个对象映射到另一个对象,这个过程中可能需要编写大量的重复性代码,如果每次都手动编写,不仅会影响开发效率,而且当项目越来越复杂.庞大的时候还容易出现错误.为了解决这个 ...

  6. git使用其它

    创建目录 切换到本地新建的dev分支,目录下还是这个目录下的文件.我push一下,指定推送到dev分支,那么dev分支就在远程仓库同步创建,并且文件也是本地这个目录下的文件,一样的. 好像得改个名字才 ...

  7. 使用systemctl管理服务(nginx)

    首先调整好路径信息,修改配置文件vim /usr/lib/systemd/system/nginx.service [Unit]Description=The nginx HTTP and rever ...

  8. MyBatis抛出BindingException异常可能是你忘了配置资源拷贝

    最近博主在搭建Mybatis项目时遇到了一问题,在一切配置妥当后,开始运行测试代码,但是此时控制台无情的抛出了异常: 开始寻找问题根源 咦?难道是我哪里写错,我的第一反应是我的xml配置文件哪里写错了 ...

  9. DRF之通过GenericAPIView的视图子类实现数据的增删改查接口

    1.安装DRF pip install djangorestframework 2.将DRF注册到APP中 INSTALLED_APPS = [ 'django.contrib.admin', 'dj ...

  10. SwiftUI(一)- VStack、HStack、ZStack布局

    SwiftUI是什么 懒得写,直接找了一篇博客: 初识 SwiftUI 三种布局 SwiftUI包括三种布局: VStack: 纵向布局,默认居中对齐 HStack: 横向布局,默认居中对齐 ZSta ...