NUNit 和 C# - 从头开始​​自动化 API 测试的教程

2025-05-25

NUNit 和 C# - 从头开始​​自动化 API 测试的教程

您是否曾尝试过自动化 API 测试,但却不知如何开始?本教程将帮助您从零开始使用 NUNit 和 C# 实现 API 测试的自动化,帮助您了解待测试的 API、测试 API 时的主要关注点、测试设置以及如何自动化测试。

目录

  • 自动化之前
  • 了解将要测试的 API
  • 测试场景
  • 设置
  • 第一个场景的自动化——GET方法
    • 创建一个将会失败的测试
    • 使此测试通过
    • 重构
  • 自动化其他场景——POST、PUT 和 DELETE 方法
    • POST 方法
    • PUT 方法
    • DELETE 方法
  • 结论

自动化之前

在开始自动化之前,我们需要了解要测试什么以及要进行哪些类型的测试。
在需要实现项目自动化时,会用到很多方法。在本教程中,我们将使用测试金字塔来确定要自动化的测试类型。
简单来说,测试金字塔是一个框架,可以帮助开发人员和 QA 人员创建高质量的软件,并帮助团队构建更可靠的测试套件。

测试金字塔

测试金字塔分为三个层次:

  • 单元测试:它们是金字塔的基础,负责测试单个组件或功能,以验证它们在隔离条件下是否按预期工作。
  • 集成测试:从根本上说,它们测试功能如何与外部依赖项进行通信。
  • 端到端:测试以确保整个应用程序是否按预期工作。

对于 API 测试,我们将自动化金字塔的第二层,即集成测试。在测试这一层时,我们需要牢记:

  • 由于与外部依赖项的集成,此测试的运行速度可能比单元测试慢
  • 我们需要一个预生产环境来运行它们。

了解将要测试的 API

在本教程中,我们将使用 FakeAPI 以及返回图书的端点。
关于 API:

  {
    "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"
  },
Enter fullscreen mode Exit fullscreen mode
  • 身份验证:无
  • 可用的方法:
    • 获取所有书籍
    • 搜索特定书籍
    • 创建新书
    • 更新书籍
    • 删除书籍

测试场景

现在我们定义了测试级别并了解了 API,我们可以开始编写测试了。在集成级别测试 API 时,我们需要考虑:

  • 状态代码
  • 正文响应内容
  • 如果 API 能够验证查询参数或正文内容

因此,对于此 API,我们将自动执行以下测试:

测试 预期结果
搜索书籍 状态代码 200
搜索书籍 有效的身体反应
搜索书籍 状态代码 200
创建一本书 状态代码 200
更新书籍 状态代码 200
删除书籍 状态代码 200

设置

要安装依赖项,我们将使用 Nuget 包管理,在您的 IDE( Visual StudioRider )上创建项目后,转到:

  • Visual Studio:工具 > 管理 Nuget 包 > 管理解决方案的 Nuget 包
  • Rider:工具 > Nuget > 管理项目的 Nuget 包并安装项目的依赖项。

第一个场景的自动化——GET方法

创建一个名为FakeApiTests.cs的新文件,我们将在此文件中编写测试。
之后,我们需要为该类导入依赖项:

using System.Net;
using FluentAssertions;
using RestSharp;
Enter fullscreen mode Exit fullscreen mode

为了帮助我们实现测试自动化,我们将使用 TDD 方法,步骤如下:

  • 创建失败的测试
  • 使此测试通过
  • 重构

TDD 流程

创建一个将会失败的测试

可以返回错误的测试是:调用所有书籍的 GET API 并等待状态代码为 400,而不是 200。
首先,我们将创建测试方法:

using System.Net;
using System.Text.Json;
using FluentAssertions;
using RestSharp;

public class FakeApiTests
{
    [Test]
    public void SearchBooks()
    {

    }
}
Enter fullscreen mode Exit fullscreen mode

该 Test 属性是将 TestFixture 类中的方法标记为测试的一种方式。它通常用于简单(非参数化)测试,但也可以应用于参数化测试,而不会导致生成任何额外的测试用例。您可以在此处查看更多符号。

在自动化测试时,我们使用 3A 方法:

  • 安排:设置所有信息以执行请求
  • 行动:提出请求
  • 断言:验证响应

从安排开始,我们需要告知 RestSharp 请求中将使用什么。首先,我们将使用 RestClient 类创建客户端:

RestClient client = new RestClient(baseUrl);
Enter fullscreen mode Exit fullscreen mode

之后,我们将使用 RestRequest 类传递有关请求的信息。此时,如果有必要,我们必须提供 URL 和有关请求的其他信息:

RestRequest restRequest = new RestRequest(baseUrl, Method.Get);
Enter fullscreen mode Exit fullscreen mode

现在我们可以进行测试了:

RestResponse restResponse = client.Execute(restRequest);
Enter fullscreen mode Exit fullscreen mode

最后,我们可以使用这个 restResponse 来进行验证:

    restResponse.Should().NotBeNull();
    restResponse.StatusCode.Should().Be(HttpStatusCode.BadRequest);
Enter fullscreen mode Exit fullscreen mode

因此,目前我们的测试如下所示:

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

使此测试通过

为了使我们的测试通过,我们只需要更新断言:

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

重构

现在,是时候进行重构了。重构的最佳方法是思考哪些代码可以在测试中复用。我们知道每个测试都需要执行请求,因此,我们可以从测试类中取出这个方法,并创建一个名为“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;
    }

}
Enter fullscreen mode Exit fullscreen mode

这个新方法将返回我们的 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);
    }
}
Enter fullscreen mode Exit fullscreen mode

之后,我们的测试通过,我们可以对其他方法重复相同的步骤。


自动化其他场景——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; }
}
Enter fullscreen mode Exit fullscreen mode

接下来,在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;  
}
Enter fullscreen mode Exit fullscreen mode

生成请求体所调用的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"  
    };  
}
Enter fullscreen mode Exit fullscreen mode

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();  
}
Enter fullscreen mode Exit fullscreen mode

为了验证正文响应的内容,我对响应的内容进行了反序列化以做出断言。

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"  
    };  
}
Enter fullscreen mode Exit fullscreen mode

对于负责发出请求的方法,我们将对 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;
    }
Enter fullscreen mode Exit fullscreen mode

测试类:

    [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();
    }
Enter fullscreen mode Exit fullscreen mode

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;
    }
Enter fullscreen mode Exit fullscreen mode

测试类:

  [Test]
    public void DeleteABook()
    {
        RestResponse response = request.DeleteFakeApiRequest(15);
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        response.Content.Should().NotBeNull();
    }
Enter fullscreen mode Exit fullscreen mode

结论

这是一个教程,我将分享我学习 NUnit 和 C# 的所有知识,包括框架文档以及我在工作中的实践。你可以在这里查看完整的项目。希望这些内容对你有用,如有任何疑问,请联系我!
Bisous, à bientot 💅🏼

文章来源:https://dev.to/m4rri4nne/nunit-and-c-tutorial-to-automate-your-api-tests-from-scratch-24nf
PREV
我创建了一个终端风格的网站。
NEXT
提升 Postman 使用体验 - 第一部分