TDD với xUnit trên dự án .NET

Kiểm thử trong .NET

Kiểm thử trong .NET: Có nhiều công cụ khác nhau có sẵn để kiểm thử các ứng dụng .NET, chẳng hạn như .NET CLI hoặc tích hợp với Môi trường phát triển (IDE).

Các loại kiểm thử: Có các bài kiểm thử tự động là một cách tuyệt vời để đảm bảo rằng mã ứng dụng thực hiện những gì mà chúng ta dự định.

Kiểm thử đơn vị là bài kiểm thử thực hiện các thành phần hoặc phương pháp phần mềm riêng lẻ, còn được gọi là "đơn vị công việc". Các bài kiểm thử đơn vị chỉ nên kiểm tra mã trong tầm kiểm soát của nhà phát triển, không kiểm thử các mối quan hệ về cơ sở hạ tầng. Mối quan hệ với cơ sở hạ tầng bao gồm việc tương tác với cơ sở dữ liệu, hệ thống tệp và tài nguyên mạng.

Kiểm thử tích hợp khác với bài kiểm tra đơn vị ở chỗ nó thực hiện khả năng hoạt động cùng nhau của hai hoặc nhiều thành phần phần mềm, còn được gọi là "tích hợp" của chúng. Các bài kiểm tra này hoạt động trên phạm vi rộng hơn của hệ thống được kiểm thử, trong khi các bài kiểm thử đơn vị tập trung vào các thành phần riêng lẻ. Thông thường, các bài kiểm thử tích hợp bao gồm các vấn đề cơ sở hạ tầng.

Kiểm thử tải nhằm mục đích xác định xem hệ thống có thể xử lý một tác vụ tải cụ thể hay không, ví dụ: số lượng người dùng đồng thời sử dụng một ứng dụng và khả năng xử lý các tương tác của ứng dụng một cách nhanh chóng.

Cân nhắc kiểm tra: Hãy nhớ rằng có những phương pháp hay nhất để viết trường hợp kiểm thử. Ví dụ: Phát triển theo hướng kiểm thử (TDD) là khi một bài kiểm thử đơn vị được viết trước khi viết mã lệnh mà nó dùng để kiểm thử. TDD giống như tạo dàn ý cho một cuốn sách trước khi bạn viết nó. Nó có nghĩa là để giúp các nhà phát triển viết mã lệnh đơn giản hơn, dễ đọc hơn và hiệu quả hơn.

Các công cụ kiểm tra: .NET là một nền tảng phát triển đa ngôn ngữ và bạn có thể viết nhiều kiểu kiểm tra khác nhau cho C#, F# và Visual Basic. Đối với mỗi ngôn ngữ này, bạn có thể chọn giữa một số khung kiểm thử (test framework):

  • xUnit là một công cụ kiểm thử đơn vị miễn phí, mã nguồn mở, tập trung vào cộng đồng cho .NET. Được viết bởi nhà phát triển ban đầu NUnit v2, xUnit.net là công nghệ mới nhất để kiểm tra đơn vị các ứng dụng .NET. xUnit.net hoạt động với ReSharper, CodeRush, TestDriven.NET và Xamarin. Đây là một dự án thuộc .NET Foundation và hoạt động theo quy tắc ứng xử của .NET Foundation.
  • NUnit là một khuôn khổ kiểm tra đơn vị cho tất cả các ngôn ngữ .NET. Ban đầu được chuyển từ JUnit, bản phát hành sản xuất hiện tại đã được viết lại với nhiều tính năng mới và hỗ trợ cho một loạt các nền tảng .NET. NUnit cũng là một dự án của .NET Foundation.
  • MSTest là khung kiểm thử của Microsoft cho tất cả các ngôn ngữ .NET. Nó có thể mở rộng và hoạt động với cả .NET CLI và Visual Studio.

Kiểm thử đơn vị trong C# sử dụng lệnh dotnet test và xUnit

Kiểm thử đơn vị được sử dụng nhiều trong nền tảng .NET cũng như các nền tảng/ngôn ngữ lập trình khác thì chúng ta nên sử dụng xUnit trong các dự án .NET.

Để bắt đầu với phát triển hướng kiểm thử trên nền tảng .NET sử dụng xUnit chúng ta thực hiện các bước sau:

  1. Tạo thư mục và giải pháp cho toàn bộ các dự án (bao gồm cả kiểm thử)
    $ dotnet new sln -o tdd-with-xunit
  2. Tạo dự án lớp thư viện
    • Tạo dự án lớp thư viện
      $ cd ./tdd-with-xunit
      $ dotnet new classlib -o SinhNX.Lib
    • Thêm dự án vào giải pháp tdd-with-xunit
      $ dotnet sln add ./SinhNX.Lib/SinhNX.Lib.csproj  
      Project `SinhNX.Lib/SinhNX.Lib.csproj` added to the solution.
    • Định nghĩa lớp QuadraticEquation2 rỗng trong dự án vừa tạo:
      • Tạo tệp QuadraticEquation2.cs
        $ cd ./SinhNX.Lib
        $ touch QuadraticEquation2.cs

         

      • Thêm mã nguồn sau vào tệp QuadraticEquation2.cs
        using System;
        
        namespace SinhNX.Lib
        {
            public class QuadraticEquation2
            {
                public double A { set; get; }
                public double B { set; get; }
                public double C { set; get; }
                public double[] SolveEquation()
                {
                    return null;
                }
            }
        }
  3. Tạo dự án kiểm thử
    • Chuyển về thư mục của giải pháp và tạo dự án
      $ cd ../
      $ dotnet new xunit -o SinhNX.Lib.Test
    • Thêm dự án vào giải pháp
      $ dotnet sln add SinhNX.Lib.Test/SinhNX.Lib.Test.csproj 
      Project `SinhNX.Lib.Test/SinhNX.Lib.Test.csproj` added to the solution.
    • Chuyển vào thư mục SinhNX.Lib.Test, thêm tham chiếu vào dự án SinhNX.Lib
      $ cd ./SinhNX.Lib.Test
      $ dotnet add reference ../SinhNX.Lib/SinhNX.Lib.csproj 
      Reference `..\SinhNX.Lib\SinhNX.Lib.csproj` added to the project.
    • Tạo lớp  QuadraticEquation2Test để kiểm thử lớp  QuadraticEquation2
      • Tạo tệp  QuadraticEquation2Test.cs
        $ touch  QuadraticEquation2Test.cs
      • Thay đổi mã nguồn lớp  QuadraticEquation2Test
        using System;
        using Xunit;
        using SinhNX.Lib;
        
        namespace SinhNX.Lib.Test
        {
            public class QuadraticEquation2Test
            {
                [Fact]
                public void SolveEquationTest0()
                {
                    QuadraticEquation2 qe2 = new QuadraticEquation2();
                    qe2.A = 1;
                    qe2.B = 1;
                    qe2.C = 4;
                    double[] expected = { };
                    double[] result = qe2.SolveEquation();
                    Assert.Equal(result.Length, 0);
                }
                [Fact]
                public void SolveEquationTest1()
                {
                    QuadraticEquation2 qe2 = new QuadraticEquation2();
                    qe2.A = 1;
                    qe2.B = 2;
                    qe2.C = 1;
        
                    double[] expected = { -1 };
                    double[] result = qe2.SolveEquation();
                    Assert.Equal<double[]>(expected, result);
                }
                [Theory]
                [InlineData(1, 4, 3, new double[] { -1, -3 })]
                [InlineData(1, -4, 3, new double[] { 1, 3 })]
                [InlineData(1, -10, 9, new double[] { 1, 9 })]
                [InlineData(1, -20, 19, new double[] { 1, 19 })]
                public void SolveEquationTest2(double a, double b, double c, double[] expected)
                {
                    QuadraticEquation2 qe2 = new QuadraticEquation2();
                    qe2.A = a;
                    qe2.B = b;
                    qe2.C = c;
        
                    double[] result = qe2.SolveEquation();
                    Array.Sort(expected);
                    Array.Sort(result);
                    Assert.Equal<double[]>(expected, result);
                }
            }
        }
  4. Chạy dự án kiểm thử (tất cả kết quả kiểm thử lỗi)
    $ dotnet test
    ...
    Failed!  - Failed:     6, Passed:     0, Skipped:     0, Total:     6, Duration: 8 ms
  5. Tái cấu trúc mã nguồn lớp QuadraticEquation2 của dự án lớp thư viện
    using System;
    
    namespace SinhNX.Lib
    {
        public class QuadraticEquation2
        {
            public double A { set; get; }
            public double B { set; get; }
            public double C { set; get; }
            public double[] SolveEquation()
            {
                double delta = B*B - 4*A*C;
                if(delta<0){
                    return new double[0];
                } else if(delta == 0){
                    double[] rs = new double[1];
                    rs[0] = -B/(2*A);
                    return rs;
                } else {
                    double[] rs = new double[2];
                    rs[0] = (-B + Math.Sqrt(delta))/(2*A);
                    rs[1] = (-B - Math.Sqrt(delta))/(2*A);
                    return rs;
                }
            }
        }
    }
  6. Chạy dự án kiểm thử xem đã qua kết kiểm thử hay chưa?
    $ dotnet test
    Passed!  - Failed:     0, Passed:     6, Skipped:     0, Total:     6, Duration: 3 ms

Nếu bước 6 chạy Failed! thì quay lại bước 5 tái cấu trúc mã nguồn đến khi nào Passed! thì hoàn thành phát triển.