NUNit 和 C# - 从头开始自动化 API 测试的教程
您是否曾尝试过自动化 API 测试,但却不知如何开始?本教程将帮助您从零开始使用 NUNit 和 C# 实现 API 测试的自动化,帮助您了解待测试的 API、测试 API 时的主要关注点、测试设置以及如何自动化测试。
目录
- 自动化之前
- 了解将要测试的 API
- 测试场景
- 设置
- 第一个场景的自动化——GET方法
- 创建一个将会失败的测试
- 使此测试通过
- 重构
- 自动化其他场景——POST、PUT 和 DELETE 方法
- POST 方法
- PUT 方法
- DELETE 方法
- 结论
自动化之前
在开始自动化之前,我们需要了解要测试什么以及要进行哪些类型的测试。
在需要实现项目自动化时,会用到很多方法。在本教程中,我们将使用测试金字塔来确定要自动化的测试类型。
简单来说,测试金字塔是一个框架,可以帮助开发人员和 QA 人员创建高质量的软件,并帮助团队构建更可靠的测试套件。
测试金字塔分为三个层次:
- 单元测试:它们是金字塔的基础,负责测试单个组件或功能,以验证它们在隔离条件下是否按预期工作。
- 集成测试:从根本上说,它们测试功能如何与外部依赖项进行通信。
- 端到端:测试以确保整个应用程序是否按预期工作。
对于 API 测试,我们将自动化金字塔的第二层,即集成测试。在测试这一层时,我们需要牢记:
- 由于与外部依赖项的集成,此测试的运行速度可能比单元测试慢
- 我们需要一个预生产环境来运行它们。
了解将要测试的 API
在本教程中,我们将使用 FakeAPI 以及返回图书的端点。
关于 API:
- 基本网址:“ https://fakerestapi.azurewebsites.net ”
- 正文响应格式:
{
"id": 1,
"title": "Book 1",
"description": "Lorem nonumy iusto takimata ut sit ut consetetur erat sanctus sed vel ut labore nulla et consetetur sed nonumy. Adipiscing hendrerit gubergren elitr at no\n",
"pageCount": 100,
"excerpt": "Nonumy duo no. Clita invidunt hendrerit lorem ea sed ipsum. Nonummy labore ut at lorem feugiat erat sit dolor sit et velit. Dolore sit lorem diam sit ipsum at stet elit kasd et et.\nJusto te accusam amet ea aliquyam iriure at et ea nihil esse nibh volutpat eros et. Eu consequat exerci voluptua dolor nonumy erat invidunt consetetur vel takimata veniam at zzril kasd dolor amet diam. Lorem kasd ipsum. Quod justo minim takimata dolor dolore sanctus clita diam dolore duis voluptua nonumy nibh cum velit tempor no. Velit suscipit diam ea sanctus consetetur dignissim magna dolor.\n",
"publishDate": "2023-09-05T15:30:40.6574078+00:00"
},
- 身份验证:无
- 可用的方法:
- 获取所有书籍
- 搜索特定书籍
- 创建新书
- 更新书籍
- 删除书籍
测试场景
现在我们定义了测试级别并了解了 API,我们可以开始编写测试了。在集成级别测试 API 时,我们需要考虑:
- 状态代码
- 正文响应内容
- 如果 API 能够验证查询参数或正文内容
因此,对于此 API,我们将自动执行以下测试:
测试 | 预期结果 |
---|---|
搜索书籍 | 状态代码 200 |
搜索书籍 | 有效的身体反应 |
搜索书籍 | 状态代码 200 |
创建一本书 | 状态代码 200 |
更新书籍 | 状态代码 200 |
删除书籍 | 状态代码 200 |
设置
要安装依赖项,我们将使用 Nuget 包管理,在您的 IDE( Visual Studio或Rider )上创建项目后,转到:
- Visual Studio:工具 > 管理 Nuget 包 > 管理解决方案的 Nuget 包
- Rider:工具 > Nuget > 管理项目的 Nuget 包并安装项目的依赖项。
第一个场景的自动化——GET方法
创建一个名为FakeApiTests.cs的新文件,我们将在此文件中编写测试。
之后,我们需要为该类导入依赖项:
using System.Net;
using FluentAssertions;
using RestSharp;
为了帮助我们实现测试自动化,我们将使用 TDD 方法,步骤如下:
- 创建失败的测试
- 使此测试通过
- 重构
创建一个将会失败的测试
可以返回错误的测试是:调用所有书籍的 GET API 并等待状态代码为 400,而不是 200。
首先,我们将创建测试方法:
using System.Net;
using System.Text.Json;
using FluentAssertions;
using RestSharp;
public class FakeApiTests
{
[Test]
public void SearchBooks()
{
}
}
该 Test
属性是将 TestFixture 类中的方法标记为测试的一种方式。它通常用于简单(非参数化)测试,但也可以应用于参数化测试,而不会导致生成任何额外的测试用例。您可以在此处查看更多符号。
在自动化测试时,我们使用 3A 方法:
- 安排:设置所有信息以执行请求
- 行动:提出请求
- 断言:验证响应
从安排开始,我们需要告知 RestSharp 请求中将使用什么。首先,我们将使用 RestClient 类创建客户端:
RestClient client = new RestClient(baseUrl);
之后,我们将使用 RestRequest 类传递有关请求的信息。此时,如果有必要,我们必须提供 URL 和有关请求的其他信息:
RestRequest restRequest = new RestRequest(baseUrl, Method.Get);
现在我们可以进行测试了:
RestResponse restResponse = client.Execute(restRequest);
最后,我们可以使用这个 restResponse 来进行验证:
restResponse.Should().NotBeNull();
restResponse.StatusCode.Should().Be(HttpStatusCode.BadRequest);
因此,目前我们的测试如下所示:
using System.Net;
using System.Text.Json;
using FluentAssertions;
using RestSharp;
public class FakeApiTests
{
[Test]
public void SearchBooks()
{
var baseUrl = "https://fakerestapi.azurewebsites.net/api/v1/Books";
RestClient client = new RestClient(baseUrl);
RestRequest restRequest = new RestRequest(baseUrl, Method.Get);
RestResponse restResponse = client.Execute(restRequest);
restResponse.Should().NotBeNull();
restResponse.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}
}
使此测试通过
为了使我们的测试通过,我们只需要更新断言:
using System.Net;
using System.Text.Json;
using FluentAssertions;
using RestSharp;
public class FakeApiTests
{
[Test]
public void SearchBooks()
{
var baseUrl = "https://fakerestapi.azurewebsites.net/api/v1/Books";
RestClient client = new RestClient(baseUrl);
RestRequest restRequest = new RestRequest(baseUrl, Method.Get);
RestResponse restResponse = client.Execute(restRequest);
restResponse.Should().NotBeNull();
restResponse.StatusCode.Should().Be(HttpStatusCode.OK);
}
}
重构
现在,是时候进行重构了。重构的最佳方法是思考哪些代码可以在测试中复用。我们知道每个测试都需要执行请求,因此,我们可以从测试类中取出这个方法,并创建一个名为“Requests.cs”的新方法:
using RestSharp;
public class RequestClass
{
var baseUrl = "https://fakerestapi.azurewebsites.net/api/v1/Books";
public RestResponse GetFakeApiRequest()
{
RestClient client = new RestClient(baseUrl);
RestRequest restRequest = new RestRequest(baseUrl, Method.Get);
RestResponse restResponse = client.Execute(restRequest);
return restResponse;
}
}
这个新方法将返回我们的 restResponse,并且在更新测试类时,我们需要在使用它之前实例化这个类:
using System.Net;
using System.Text.Json;
using FluentAssertions;
using RestSharp;
public class FakeApiTests
{
RequestClass request = new RequestClass();
[Test]
public void SearchBooks()
{
RestResponse response = request.GetFakeApiRequest();
restResponse.Should().NotBeNull();
restResponse.StatusCode.Should().Be(HttpStatusCode.OK);
}
}
之后,我们的测试通过,我们可以对其他方法重复相同的步骤。
自动化其他场景——POST、PUT 和 DELETE 方法
POST 方法
创建书籍时,我们将使用 POST 方法,为此,我们需要传递一个主体请求。
首先,我们将创建一个名为FakeApiEntities.cs的新类,并在该类中创建一个具有主体请求/响应属性的对象。
为什么要使用它?如果 API 将来发生变化,修改起来会更容易
。
using System.Text.Json.Serialization;
public class FakeApiEntities
{
[JsonPropertyName("id")]
public int? Id { get; set; }
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("description")]
public string Description { get; set; }
[JsonPropertyName("pageCount")]
public int PageCount { get; set; }
[JsonPropertyName("excerpt")]
public string Excerpt { get; set; }
[JsonPropertyName("publishDate")]
public string PublishDate { get; set; }
}
接下来,在Request.cs类中创建发出请求的新方法:
public RestResponse PostFakeApiRequest()
{
RestClient client = new RestClient(baseUrl);
var body = BuildBodyRequest();
RestRequest restRequest = new RestRequest(baseUrl, Method.Post);
restRequest.AddBody(body, ContentType.Json);
RestResponse restResponse = client.Execute(restRequest);
return restResponse;
}
生成请求体所调用的BuildBodyRequest方法,我们使用FakeApiEntities类来生成一个新的对象:
public static FakeApiEntities BuildBodyRequest()
{
return new FakeApiEntities
{
Id = 100,
Title = "Test Book",
Description = "Mussum Ipsum, cacilds vidis litro abertis. Quem num gosta di mim que vai caçá sua turmis!",
Excerpt = "uem num gosta di mim que vai caçá sua turmis!",
PageCount = 100,
PublishDate = "2023-09-03T13:50:32.6884665+00:00"
};
}
Test.cs 文件中的测试方法将是:
[Test]
public void CreateABook()
{
RestResponse response = request.PostFakeApiRequest();
response.StatusCode.Should().Be(HttpStatusCode.OK);
response.Content.Should().NotBeNull();
var bodyContent = JsonSerializer.Deserialize<FakeApiEntities>(response.Content);
bodyContent.Id.Should().NotBeNull();
bodyContent.Description.Should().NotBeNull();
bodyContent.Title.Should().NotBeNull();
}
为了验证正文响应的内容,我对响应的内容进行了反序列化以做出断言。
PUT 方法
对于 PUT 方法,我们基本上使用相同的步骤,但也有一些区别。
首先,我们将更改负责生成主体请求的方法。用于更新图书的端点使用相同的主体,但是,我们需要在主体请求中传递与 URL 中发送的相同的 ID。因此,我们将此参数设为非强制参数,并使用三元运算符来确保使用此主体的其他测试不会失败:
public static FakeApiEntities BuildBodyRequest(int? id=null)
{
return new FakeApiEntities
{
Id = id ?? 100,
Title = "Test Book",
Description = "Mussum Ipsum, cacilds vidis litro abertis. Quem num gosta di mim que vai caçá sua turmis!",
Excerpt = "uem num gosta di mim que vai caçá sua turmis!",
PageCount = 100,
PublishDate = "2023-09-03T13:50:32.6884665+00:00"
};
}
对于负责发出请求的方法,我们将对 RestRequest 类使用的 url 进行更改,以接受将要更新的书籍的 Id:
public RestResponse PutFakeApiRequest(int id)
{
RestClient client = new RestClient(baseUrl);
var body = BuildBodyRequest(id);
RestRequest restRequest = new RestRequest( $"{baseUrl}/{id}", Method.Put);
restRequest.AddBody(body, ContentType.Json);
RestResponse restResponse = client.Execute(restRequest);
return restResponse;
}
测试类:
[Test]
public void UpdateABook()
{
RestResponse response = request.PutFakeApiRequest(15);
response.StatusCode.Should().Be(HttpStatusCode.OK);
response.Content.Should().NotBeNull();
var bodyContent = JsonSerializer.Deserialize<FakeApiEntities>(response.Content);
bodyContent.Id.Should().NotBeNull();
bodyContent.Id.Should().Be(15);
bodyContent.Description.Should().NotBeNull();
bodyContent.Title.Should().NotBeNull();
}
DELETE 方法
DELETE 方法与 GET 方法类似,我们将允许此方法接收 ID 并更改 RestRequest 类调用的方法:
public RestResponse DeleteFakeApiRequest(int id)
{
RestClient client = new RestClient(baseUrl);
var body = BuildBodyRequest(id);
RestRequest restRequest = new RestRequest( $"{baseUrl}/{id}", Method.Delete);
restRequest.AddBody(body, ContentType.Json);
RestResponse restResponse = client.Execute(restRequest);
return restResponse;
}
测试类:
[Test]
public void DeleteABook()
{
RestResponse response = request.DeleteFakeApiRequest(15);
response.StatusCode.Should().Be(HttpStatusCode.OK);
response.Content.Should().NotBeNull();
}
结论
这是一个教程,我将分享我学习 NUnit 和 C# 的所有知识,包括框架文档以及我在工作中的实践。你可以在这里查看完整的项目。希望这些内容对你有用,如有任何疑问,请联系我!
Bisous, à bientot 💅🏼