In our previous article, “Getting Automated API Testing done (1) – Start with a Good Json Validator,” we talked about three problems with the lack of automated API testing:

1. API implementation is inconsistent with design, such as missing fields or incorrect field types. 2. API cannot form a complete closed loop and lacks functions. New features can cause bugs in existing apis, and manual regression testing is time-consuming and tedious

The first of these, in the last article, I explained the idea and practice of solving this problem with a JSON-Validator.

This article will attempt to illustrate my thoughts on the remaining two issues, aimed at ensuring the delivery of high-quality apis through more efficient automated testing.

Automated test process

I have been in the habit of writing automated tests for a long time, but I have not been able to achieve the best results. I have been reflecting on the causes of the problems, and recently I have some ideas. The main reason is that in the past, writing tests depended on feeling, feeling what needed to be tested, writing a test, all thinking is fragmented, there is no systematic thinking process, and there is no reasonable process to ensure.

Indeed, a good process, whether it’s development or testing, ensures that things move more smoothly and helps us focus our minds on a smaller range of issues to achieve better results.

For automated testing, too, we need to have a reasonable process that divides the work involved into several phases, each focusing on different points and avoiding the distraction of too much attention at the same time.

So, as far as I’m concerned, it makes sense to divide automated testing into the following three stages:

1. Design of test cases; 2. Structure of test code; 3

In the following pages, I will describe in detail the main concerns of each stage and how to do each stage better

Design of test cases

Whether automated testing or manual black box testing, test cases are very important, and the quality of test cases is directly related to the overall test effect. Therefore, our first step is to design test cases to ensure that the test cases can cover the maximum range of API usage scenarios.

So how do you design test cases well?

First, a reasonable division of the scene

In general, an API or a set of apis can satisfy the user’s multiple scenarios, in the grasp on the basis of user requirements, we need to split into multiple test scenario, these requirements by reasonable scene, on the one hand, to ensure that our API can meet user requirements, on the other hand is focused on the scope of the each test, Avoid a test that is too broad or too narrow, that is too broad and will result in inadequate testing, that is too narrow and will require a lot of tests to be written, which is time-consuming and inefficient.

Second, consider boundary conditions

Once the test cases for the main scenarios have been designed, the main logical branches of the API should be covered, and then test cases for boundary conditions need to be considered.

Common boundary conditions are as follows:

  • Permissions, what happens to users without permissions? Is 403 returned correctly

  • Invalid data submission verifies correctly, returns 400 errors

  • Exception flow in business logic

Of course, the determination of boundary conditions is very complex, and each application varies greatly according to its business, and its importance is also different. Developers should make specific decisions for specific businesses.

Third, introduce Review mechanism

It is inevitable that one person may not have thought through all of the test cases. At this time, the rest of the team can Review these test cases so that they can be optimized and adjusted earlier.

Of course, the Review mechanism works at any stage, but in general, the earlier the Review point, the more valuable it is.

Test your code’s architecture

You read that right, testing code requires architecture, and just like writing any other code, a good architecture makes maintenance easy and extension easy.

So what is the architecture of the test code to consider?

First, the selection and expansion of test library development

First of all, we need to choose the right test library to make it easier to write tests. If all tools were written manually from scratch, it would be a huge amount of work. At this point, we need to select the appropriate library for test development based on our own requirements, which may be PHPUnit with Guzzle, Codeception, or others, as FAR as I am familiar with the PHP domain.

Of course, even with off-the-shelf libraries and tools, some of the requirements are not met by these libraries, and some extension development work is required. For example, in my previous article, I developed a JSON-Validator for more rigorous validation of JSON structures.

Second, the encapsulation of basic business

In the world of code, there is a distinction between the bottom code and the top code, the bottom code is called by the top code, as the cornerstone of a software system.

The test code is similar in that the low-level code encapsulates the underlying business logic, and the upper-level code is the outermost business test that runs on the low-level code.

For example, we now need to test the “Logged-in user can post normally” scenario, which includes the “Leave user logged in” and “Post” actions. Obviously, “keeping the user logged in” should be much lower, and many operations depend on it, and it should be the domain of low-level code.

In this example, we can encapsulate the “keep the user logged in” operation as an underlying library to make it easier for other test code to call.

Said so much, sum up actually four words: stratified thought.

Test code writing

With the support of good test cases and test architecture, we finally came to “write test code”, which has the following two points to help us write test code efficiently:

1. Separate test cases from test code

Testing process, in fact is to examine the corresponding input to achieve the desired output of the process, in order to make the same section of the test code can be applied to more and more test cases, we can put the test cases and test output parameters, and the same categories of test cases to reuse the same section of the test code, to achieve the separation of test cases and test code. This allows for better scalability without modifying the test code when new test cases are added.

In PHPUnit, we can do this with built-in dataProvider functionality, and I’m sure other testing frameworks have support for this as well.

2. Keep the test code simple

Test code should be as simple as possible, preferably declarative, to give what data to what results, let people see at a glance. If the logic of the test code is complex, how can you ensure that the test code is correct? Probably defeats the purpose of test writing.

This article has ended, the overall seems a little abstract, if you have any questions, please feel free to discuss with me through the “code to Write poetry” wechat public account.

-> Click to read the first article in our series on Automated API Testing