Why are there tests?

I’ve written about DevOPS development before to understand what DevOPS is and see how testing plays a role in the overall development process.

When the architecture evolved to the second stage of agile development, since we could not fully understand what the real needs of users were, we kept breaking down a large goal into small deliverable goals, and then continued to develop in small steps through constant iteration.

This is where development and testing mix and alternate development, where small deliverable goals are guaranteed to be usable, and testing is essential. Testing has become an integral part of the DevOPS process, including the evolution to microservices architecture.

What types of tests are included?

Unit test purpose: used to verify the correctness of coding units, such as testing the logic correctness of a method. It belongs to white box test, that is, the internal logic of the tested object is transparent to the tester, and is generally written by the developer.

Integration test: Is used to validate the detailed design, also called assembly test, the subsystem test, is on the basis of the unit test, will be involved in the upstream and downstream dependence, database, middleware, cache access real content, rather than the mock content of unit tests, will involve the modules are assembled to form a subsystem, look at this subsystem functions can be normal service, Meet the detailed design requirements, belong to the black box test.

System test purpose: used to verify the outline design, test the correctness of each system function, belongs to the white box test, the tester to do.

Regression test purpose: to verify that defects are correctly fixed and changes to the system do not affect previous functions. This is generally done by re-executing all test cases established in the early testing phase to verify the correctness of the problem modification.

Why unit tests?

Development phase, in fact we will have a test, whether local fabricated data call interface, or write a main function directly under the simple test to delete, will be tested, but this way of measurement is not comprehensive, various parameters of the test results also didn’t get the record, it is easy to appear some situation didn’t consider completely, or process without test. If the write unit tests, the online test run when there will be a unit test coverage statistics, which is no test to be clear at a glance, online can also increase confidence, otherwise not only their lack, adding some logic after need regression testing, the testing process is to manually again? It’s also inefficient.

In the iteration phase, a stable system, if we change something, how do we make sure it doesn’t affect the rest of the logic? Run the other test cases to see if they can pass. If they fail, there is a problem. Therefore, unit testing is the most powerful means to ensure the correctness of the refactoring, with enough single tests to be free to refactor the code.

Seven characteristics of unit testing

  1. Automated unit testing needs to be automated.

We started out with a concept called Daily Build, which was a release every day of the development cycle for leaders, product managers, testers, front and back developers to keep track of the progress of the project. This required continuous integration, automated test execution, and testing definitely needed to be integrated into the DevOPS automation process.

After the online continuous integration unit test is completed, quality indicators such as branch coverage, line coverage, automation execution time, and unit test pass rate can be displayed. Each company will have quality score requirements, which cannot be met, so I am sorry that the online test cannot be launched.

  1. Execution is fast enough.

When a project is larger, it is normal to write hundreds or thousands of test cases. If it takes hours to run these test cases, let alone daily builds, weekly builds can be difficult to endure once a week, so you need to find a way to reduce this execution time and improve delivery speed.

  1. You cannot rely on other tests or other test execution sequences; a unit test is independent.

There are a hundred test cases, so the hundred should be independent, ninety-nine of them succeed, one failure only affects that one test case, there should be no test dependency. So in an automated process, if you run a failed test case, you can rerun the test case at any time, and the operation is idempotent.

  1. You can’t rely on external resources.

Such as database access, file permissions, network connection, or some third party API interface such as resources, testers can think of some way to mock ways to mock these calls, or services of a pile of upstream and downstream, you said you want to test an interface to find the downstream service classmates give you permission, then you invented a lot of garbage data, The upstream and downstream services involve a bunch of people who are going to fight, and this test is going to be impossible to work with. Therefore, tests should not rely on external resources.

  1. Unit test execution is time and space transparent.

This means that the results are the same at any time and in any environment, not local, not online, not dependent on the runtime environment.

  1. Unit tests need to make sense.

Unit tests on get,set methods and Hashcode methods of some beans are simply to gather code coverage, which is of little significance. Some main branches of the main process need to be tested.

There is also the database DB operation, if only the test DAO method pretend to insert data, then there is no point, you need to actually insert and then delete.

  1. Unit testing should not be treated as special, it is just as important as coding!

For example, if you want to make a live action, the live change is just some configuration file changes, this change is actually very dangerous, should be treated as the configuration source code, test announcements, configuration version management, etc.

Mockito & Assert

Here I am not going to write the specific use of these two tools, just introduction, specific use to see if you want to arrange to write a later article.

I said you can’t rely on external sources for a single test, but the actual code does have these operations, so how to do? This is where Mockito comes in, as well as PowerMock and its counterparts in other languages. Assert assertions are used in conjunction with mocks to determine whether the results returned are expected or not.

What actions do you mock? The mock scenarios:

  1. The most common mock scenario is an RPC call to an external resource
  2. Take the database connection, add delete change check data
  3. The download file
  4. email
  5. Call the printer to print files, etc

There is no need to actually call these resources when the tests involve the above; Mockito can simulate these external resource calls.

Mockito features:

  1. fast
  2. reliable
  3. automation

Junit, TestNG and DEVOPS

Because these two are commonly used more, but many people do not understand the details, here through the way of comparison to introduce the two functions and differences.

Function comparison main differences:

As you can see, TestNG is more powerful than Junit4. TestNG supports Group grouping, Parameterized parameterization, Dependency Dependency tests, and different implementations of Suite tests. I’ll focus on the roles of the following suites, groups, and testing careers.

  1. Annotation Support Supports differentiation

TestNG supports many more annotations than JUnit. JUnit does not support suite annotations, group annotations, and @beforetest and @Aftertest annotations.

  1. Parameterized Indicates a parameterization test

Parameterized tests are changes in unit test parameter values. This functionality is implemented in both JUnit 4 and TestNG, but in different forms.

A JUnit parameter must be passed to a constructor parameter to initialize a class member as a parameter value for the test. The return type of the parameter class is “List []” and the data has been restricted to String or the value of the primitive type used for the test.

TestNG’s parameterized tests are flexible, introducing XML files or classes that define parameters through the @dataProvider annotation. It can support many complex data types as parameter values, such as custom objects, complex JSON types, and the possibilities are endless.

QA and QE can both provide their own data for testing in XML files. We can run the same test case with different data sets and get different test results.

Another benefit of parameterization is that JUnit 4 writes n test cases for tests with n different parameter combinations. Each test case performs essentially the same task, except that the parameters of the method under test are changed. TestNG parameterized tests require only one test case and then add the required parameters to TestNG’s XML configuration file. The advantage is that the parameters are separated from the test code and can be modified by non-programmers without recompiling the test code.

  1. Suite Test Group Test and Suite Test
  • JUnit 4 will run the suite test again if the suite fails. When TestNG fails, an XML file is created to describe the failed test, and the program is executed using this file so that successful tests are not repeated.
  • TestNG can do bundled class tests as well as bundled method tests. With TestNG’s unique grouping support, each method can be combined with a combination that allows tests to be classified (grouped) by function. The possibilities for integration testing are unlimited through the concept of “grouping” testing. For example, we can only test the “DatabaseFuntion” grouping from all unit test classes.
  • TestNG allows regression testing against failed use cases to increase specificity and efficiency, whereas Junit requires re-execution of all test cases.
  • In the automated test process, if the test case fails to run, there is usually a button, you can run the failed case with one click, do not need to run the successful case to save time.

TestNG is designed to cover all tests, including unit, functional, end-to-end, and integration tests.

  1. TestNG Dependency test Dependency test

DependsOnMethods = {“funtion name”}) dependsOnMethods = {“funtion name”}) dependsOnMethods will be executed before the required method. The test result is ignored rather than failed, so that when hundreds or thousands of use cases cannot be executed due to the failure of the dependent use case, you can only troubleshoot the cause of the dependent use case failure. Otherwise, if Junit4 were all flagged as failing, it would be a huge waste of troubleshooting and regression testing efficiency.

JUnit 4 tests are highly dependent and have a strict sequence of test cases. If the first test fails, all subsequent dependency tests fail. TestNG uses the @test dependsOnMethods attribute to address Test dependencies. If a method depends on a method that fails, it will be skipped rather than marked as a failure.

  1. TestNG is better suited for the wide range of complex integration tests that test engineers need;

This article about testing is the daily development must pay attention to the content, and the development is strongly related, here I did not talk about the specific implementation of some tools, this way of use can be directly read the document, or I will arrange another later. Thanks to Diaishanlian, like to follow my public account “xiaolongfei”, daily share back-end technology dry goods, I am xiaolongfei ~~