Software unit test focus on software minimum executable unit can perform normal, but the software is composed of a small minimum execution unit, all rely on or contact exists between the unit and the unit, so in the software development to ensure that only the smallest unit of right is often not enough, in order to ensure that the software can work correctly, Unit to unit integration testing is essential. In addition, the previous article only introduced how to use xUnit.net pairs. .net Core procedures simple (no arguments) unit testing and calculating code coverage, but in the actual test work, often through the statement coverage, condition/branch coverage (white box) and equivalence class, boundary value, etc. (black box) to design test cases, the cases of the test is crucial to test method of parameters is different, Using a no-parameter test method would require writing a large number of test methods for different test cases, which is not practical. This article will introduce how to complete data-driven testing and code-dependent integration testing based on unit testing from the following aspects:

  • Introduction to Integration Testing

  • Implement simple database integration tests using xUnit.Net

  • Regressive database integration testing

  • Introduction to data-driven testing

  • Data driven testing based on xUnit.Net

    • Theory&InlineData
    • Excel based data driven testing
  • summary

Introduction to Integration Testing

The simple understanding of integration test is that on the basis of unit test, each unit is integrated according to its dependency relationship to check whether the code can run correctly. Integration test also has different integration methods according to different software development methods or software architectures. Such as process-oriented design and object-oriented design, monolithic architecture and microservice distributed architecture and so on. This article covers only integration testing of class-to-class dependencies in object-oriented programming.

Implement simple database integration tests using xUnit.Net

Database is an indispensable component of most software systems, so integration with database is a common test scenario during integration testing. Here is how to test through xUnit.Net. 1. Write the tested code: introduce EFCore and related components into the tested project:

  

Add DBContext and the corresponding data manipulation code:

  

Note: Use LocalDB as the database to complete the test, if you use SQL Server to modify the connection string.

  

The methods of adding users and querying by name are realized in the user warehouse. Note: After the code is written, you need to migrate the entity code to the database. Run add-migration to Add the Migration code, and then run update-database to update the data to the database. For the Migration method, see docs.microsoft.com/en-us/ef/co… 2. Write test code:

  

The test code is also very simple, is to create a SQLServer user repository instance, and then through the construction of the way to inject it into the UserManager type for use, the subsequent creation of UserManager, user query methods will be implemented through the repository. 3. Test results:

  

Regressive database integration testing

Regression here refers to regression testing, which refers to the need to re-test the old code after modifying it to ensure that the change does not affect the existing code. In general, tests implemented using xUnit.Net are regressive because the test code does not change and can be repeatedly executed. In addition, the test code is managed by the code version management tool and all test methods can be re-executed when the code is modified. Tested and different but related to database, the database is a data persistence tool, the data of each operation can be persisted, suppose you have two test cases, the first is to add a data, the second is whether the query the number of the data is 1, then the two tests in the first run is no problem, However, when run again, the first use case may fail to add primary key conflicts, or the second use case may fail with a query result of 2 after successful addition, and such tests are considered non-regressive. Here’s how to use xUnit.Net to implement regression testing for database integration:

Initialize the database using constructors

The main problem with the regression of database integration tests is that the state of the database is different after each unit test. Can this be solved by initializing the database before each test? Look at the following code:

  

Start by adding a constructor for the test class, and initialize the database in the constructor.

  

Then add the number of users test assertion to the test method, and when the user is added, there should be 1 user in total. Test execution method:

  

The tests pass no matter how many times they are executed, which means that the number of users is 1 each time you add a user, which makes the test regress. But in real development, you can’t have just one test type, and if you add code to initialize the database for each test type, those unit tests will be executed very slowly (the initialization of the database is very time consuming). How do you solve this problem?

Use fixtures to share test context

Fixtures are a feature in xUnit.Net that you can use to share test context. Fixtures can be translated as fixtures, in other words, fixtures that hold something in place so that it can be used within a specified scope. There are two types of fixtures in xUnit.Net: Classfixtures and collectionfixtures. They correspond to sharing context within a test type and within a set of test types. Fixtures have many functions. Here’s how you use fixtures to share the state that your database has been initialized (you don’t need to repeat the initialization) : 1. Create a Fixture type: a Fixture is actually a plain C# type, the only thing to note is that it uses constructors to initialize data and Dispose to Dispose or clean it up. A simple Fixture type is as follows:

  

2. Use classfixtures for a single type:

  

You can see from the code that the constructor initialized has been commented out, and once you implement the IClassFixture interface, you can see that the tests are still regressive when you execute the test methods again. 3. Use icollectionFixtures for multiple types: You first need to add a type that implements icollectionFixtures to DatabaseFixture:

  

The two main points are that you need to use the CollectionDefinition feature, and then the type needs to implement the ICollectionFixture

interface. Apply the CollectionFixture on the test type by specifying the previously defined Collection name via the Collection feature:

  

Then execute the test method several times and you can see that the test is still regressive:

  

Note: When sharing test data (including database data), the test may fail because of the order in which the test method is executed. However, xUnit.Net does not provide the implementation of the order in which the test method is executed. The default method is named according to the method. Github.com/xunit/sampl…

Test data management and initialization

When it comes to database testing, it’s likely that there will be some existing test data in the database before you test it. When you write your test code using xUnit.Net, you can put the initialization of the test data into the Fixture type, but how do you manage that data? In general, using SQL scripts is a good way to manage test data for a database because it decouples the test data from the code and only requires SQL script files to maintain the data. Here is how to manage and initialize data using SQL script files in xUnit.Net: 1. Create an SQL script:

  

Note: You need to set “copy to output directory” of the file to “always copy” or “update copy” :

  

2. When Fixture types initialize the database, execute the SQL script to initialize the Data: the following code first looks for all the files in the Data directory. SQL and then executes the SQL scripts in turn.

  

3. Modify the test code (since the script added two data items, the expected value should be three) :

  

4. Perform tests:

    

The test succeeded.

Introduction to data-driven testing

As mentioned at the beginning of this article, both white-box coverage tests and black-box boundary/equivalence tests are most directly embodied in “parameters,” the parameters passed into the method being tested. These parameters are actually “test cases”. It is not reasonable to write a test method for each test case, so a method is needed to complete the test by changing the parameters and reuse the test code as much as possible. This is data-driven testing.

Data driven testing based on xUnit.Net

Theory&InlineData

Theory and InlineData are data-driven (parameterized) testing features available in xUnit.Net. Here is an example of how Theory and InlineData are used:

  

Running results:

   

InlineData makes it easy to apply data from test cases to test methods and perform desired tests. However, when a new test case is added, the code file needs to be modified, and the test case is not very convenient to manage in the code. Is there a way to manage the test case data independently?

Excel based data driven testing

XUnit.Net does not provide built-in Excel data loading function, but it is very extensible. It can implement a Theory data source provider by implementing DataAttribute:

  

1. Realize the DataAttribute abstract class and the Theory data provider of Excel: The following is the core method to realize the data loading of Excel:

  

  

  

Note the following points in the above method:

  • Two bodies: the Excel file name and the test method MethodInfo, the former used to read the Excel file, the latter used to get parameter information.
  • Obtain the parameter list of the test method by MethodInfo, including parameter types.
  • Read Excel data and match it to the parameter list of the test method. Simply put, each row of Excel data is the parameter of the corresponding test method. The test method will be executed as many times as there are rows of data.
  • When data is read as double or float in Excel but the test method requires an int, the conversion is required.

Note: The Excel file reading component used here is: github.com/ExcelDataRe…

DataAttribute Complete code: github.com/yqszt/xUnit…

2. Use ExcelDataAttribute:

  

3. Add test case data to additionTestCase.xls:

  

Note: The copy to output directory property of AdditionTestCase.xls needs to be set to “Always copy” or “Copy new files”.

4. Test method:

  

The test succeeded.

summary

This paper mainly introduces the. Net Core uses xUnit.Net to implement integration testing with the data and to initialize the database through fixtures, ensuring regression. It also introduces how to use xUnit.Net to implement data-driven testing. Data-driven testing can improve test quality simply by adding use case data, and can easily manage test cases.

Example code for this article: github.com/yqszt/xUnit…

Reference:

En.wikipedia.org/wiki/Integr… En.wikipedia.org/wiki/Data-d… Xunit. Making. IO/docs/gettin… Dotnetliberty.com/index.php/2… Github.com/MisterJames… Ikeptwalking.com/writing-dat… Wandering. Life/data – driven… Github.com/ExcelDataRe… Xunitpatterns.com/Testing%20W… Xunit. Making. IO/docs/Shared…

This paper links: www.cnblogs.com/selimsong/p…

Good code is tube out — talk about it. Net Core code management approach and implementation