What's the use of unit testing
Improve the work efficiency of the whole team.
Quality code is a contribution to the whole team
Improve the programmer's sense of responsibility and code quality.
Through unit testing, ensure that your code is reliable and complete, which is responsible for yourself and the team
Get a regression test tool for the underlying module
Continuously improve the design without destroying the existing functions
It forces you to plan well before writing code, leading to better design, including coding level.
Reduce the cost of Bug repair
Noun interpretation
Unit test: it is the test of the basic components of software. It belongs to the category of white box test. It designs test cases by analyzing the logical structure of code.
Regression test: retest the previous test after the modification to ensure the correctness of the modification.
Smoke test: developers spend less time to ensure that the function can run at least.
Stub module: simulate the "double" module of the third party, parameters and return information.
Drive module: simulate user operation and generated data, enable the tested module to transmit data to the tested module, and make expected judgment on the returned information results.
Non incremental testing: test each module separately, and finally connect all modules together for testing.
Incremental testing: test the modules to be tested and the modules that have been tested together.
Unit test requirements
Test requirements document.
Unit tests are written by the person who is most familiar with the code (the writer of the program).
Ensure the independence of unit testing, that is, test cases cannot depend on each other.
The unit test shall ensure that the test data generated will not affect the system. It is generally recommended to roll back the data generated in the test to avoid affecting the normal data of the system.
Test granularity. Generally, all methods are required to be tested (excluding get and set methods).
Assertions must be used in the test to determine whether the results meet the expected goals.
It is necessary to record the test results and have the result documents. According to the different test requirements, record selectively, analyze the results and debug them.
When the requirements change, regression testing is required to ensure that no new bug s are generated.
When involved with the third party, it is necessary to write the pile module of the third party and simulate the parameters, logic, data and return value to achieve the same effect.
I suggest that after the method parameters and names are defined, write test cases first, and then realize the functional logic.
Specification
Test class name: the column name of the class to be tested + test. For example - > the name of the class to be tested is BaseBizTest, then the name of the test class is BaseBizTest
Test method name: test + name of the tested method. For example, if the name of the tested method is getUser, the name of the test method is testGetUser
Test package name: the package name of the tested class is com yunat. Channel, the package name of the test class is test com. yunat. The project managed by channel and Maven establishes the same package path under src/test/java.
Select test framework
Choose according to different requirements. If you are testing the database, you can choose dbunit and junit. For business framework testing, you can choose spring test and junit testing framework. The following are pom dependencies:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>3.1.1.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>org.dbunit</groupId> <artifactId>dbunit</artifactId> <version>2.4.7</version> <scope>test</scope> </dependency>
Introduce junit4 annotation commonly used in 10 frameworks
@BeforeClass: the method marked by it must be a static method, which is executed when the test class object is loaded.
@AfterClass: the method marked by it must be a static method, which is executed after all methods of the test class are executed.
@Before: execute before each test method.
@After: execute after each test method.
@Ignore: indicates that the test method is ignored.
@Test: the test method is marked as drive.
@RunWith: test runner, collection runner, Suite, parameterized runner, etc.
@Suitecalasses: the type parameter of the test runner. Put your own test class and run it comprehensively, that is, set test.
For more detailed introduction, please search: junit_ Use guide and operation specification (compare junit 3 and 4) pdf.
Parameterized parameterized runner usage
Parameterized demo:
Tested class:
public class WordDealUtil { public static Object wordFormat4DB(String target) { if (target==null) return null; if ("employeeInfo".equals(target)) return "employee_info"; if ("".equals(target)) return ""; if ("EmployeeInfo".equals(target)) return "employee_info"; if ("employeeInfoA".equals(target)) return "employee_info_a"; if ("employeeAInfo".equals(target)) return "employee_a_info"; return null; } }
Test case:
/** * Produce different results for different parameters * * @author ming.peng * @date 2012-12-27 */ @RunWith(Parameterized.class) public class WordDealUtilTest { private String expected; private String target; @Parameters public static Collection<Object[]> words() { return Arrays.asList(new Object[][] { { "employee_info", "employeeInfo" }, // Test general handling { null, null }, // Processing when testing null { "", "" }, // Processing when testing an empty string { "employee_info", "EmployeeInfo" }, // Test when the first letter is capitalized { "employee_info_a", "employeeInfoA" }, // Test when the last letter is capitalized { "employee_a_info", "employeeAInfo" } // Test the case when multiple connected letters are capitalized }); } /** * Constructor required for parameterized tests * * @param expected * The expected test result corresponds to the first parameter in the parameter set * @param target * Test data, corresponding to the second parameter in the parameter set */ public WordDealUtilTest(String expected, String target) { this.expected = expected; this.target = target; } /** * Test the conversion of Java object name to database name */ @Test public void wordFormat4DB() { assertEquals(expected, WordDealUtil.wordFormat4DB(target)); } }
8. Use of spring test framework
Because most of our system frameworks use spring framework, and junit is not very convenient to test the framework, we choose spring test and junit test framework to be used together. Spring test is an expansion based on junit framework.
classpath can be used in two ways:
-
classpath*:applicationContext.xml will be added to the applicationContext.xml in the root directory of this project and all jar packages XML file, used when cross jar package dependency.
-
classpath:applicationContext.xml is only added to the file in the root directory of the project
applicationContext.xml file. It is recommended to write this when it does not depend on the configuration files of other jar packages to avoid conflicts.
The commonly used annotation
@ContextConfiguration: configure the reading resources of spring
@Transactional: transaction declaration
@TransactionConfiguration: transaction configuration
@Rollback: transaction rollback configuration
spring business component test example
package com.yunat.devtwo.biz; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.yunat.devtwo.dao.BaseDao; /** * Business test component * * @author ming.peng * @date 2012-12-26 * @since 2.2.0 */ @Component("BaseBiz") public class BaseBiz { @Autowired private BaseDao baseDao; public Map<String, Object> getUser(String userName){ Map<String, Object> parameter = new HashMap<String, Object>(1); parameter.put("userName", userName); Map<String, Object> user = baseDao.getSingleRow("Common.getUser", parameter); return user; } public Integer saveSysConfig(){ Map<String, Object> sysConfig = new HashMap<String, Object>(); sysConfig.put("name", "gateway_balance"); sysConfig.put("desc", "Channel account initialization amount"); sysConfig.put("value", "10000"); return baseDao.save("Common.saveSysConfig", sysConfig); } }
For the above business components, it is very simple to use annotation to configure test cases, as follows:
package com.yunat.devtow.biz; import java.util.Map; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; import com.yunat.devtwo.biz.BaseBiz; /** * Business component testing * * * @author ming.peng * @date 2012-12-27 * @since 2.2.0 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:spring/applicationContext.xml" }) @Transactional @TransactionConfiguration(defaultRollback=false, transactionManager="txManager") public class BaseBizTest { protected Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private BaseBiz baseBiz; @Test public void testGetUser(){ Map<String, Object> user = baseBiz.getUser("qiushi"); logger.info(user.toString()); Assert.assertEquals(77800, user.get("group_id")); } @Test public void testSaveSysConfig(){ Integer result = baseBiz.saveSysConfig(); Assert.assertEquals(result.intValue(), 1); } }
Spring test provides a very simple test for the web layer. The following test cases for spring MVC:
package com.yunat.devtwo.controller; import java.io.UnsupportedEncodingException; import java.util.Map; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.yunat.devtwo.biz.BaseBiz; /** * * spring mvc controller * * @author ming.peng * @date 2012-12-27 * @since 2.2.0 */ @Controller @RequestMapping("ccmsController") public class CcmsController { private Logger logger = Logger.getLogger(this.getClass()); @Autowired private BaseBiz baseBiz; /** * Enter the account management interface * @param userName * @param userInfo * @return */ @RequestMapping("accountManager") public ModelAndView accountManager(String userName, String userInfo, HttpSession session) { logger.info("===================>>>>get into ccms Account management center, user name:"+userName); ModelAndView mav = new ModelAndView("ccms/account"); mav.addObject("userName", userName); mav.addObject("userInfo", userInfo); System.out.println(session.getAttribute("abc")); Map<String, Object> user = baseBiz.getUser(userName); logger.info("user:" + user); baseBiz.saveSysConfig(); logger.info("===================>>>>Normal entry ccms Account management center, user name:"+userName); session.setAttribute("userName", userName); return mav; } }
It is also very simple to configure and test web layer components using annotation, as follows:
package com.yunat.devtow.controller; import javax.servlet.http.HttpSession; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; /** * CcmsControlle test * * * @author ming.peng * @date 2012-12-27 * @since 2.2.0 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:spring/applicationContext.xml", "classpath:spring/springmvc-servlet.xml" }) @Transactional @TransactionConfiguration(defaultRollback = false, transactionManager = "txManager") public class CcmsControllerTest { @Autowired private RequestMappingHandlerAdapter handlerAdapter; @Autowired private RequestMappingHandlerMapping handlerMapping; private static MockHttpServletRequest request; private static MockHttpServletResponse response; @BeforeClass public static void before() { request = new MockHttpServletRequest(); request.setCharacterEncoding("UTF-8"); response = new MockHttpServletResponse(); } @Test @Rollback(true) public void testAccountManager() { request.setRequestURI("/ccmsController/accountManager"); request.setMethod(HttpMethod.POST.name()); request.setParameter("userName", "qiushi"); request.setParameter("userInfo", "abjiozjdlfjaosdifjoaisdfji"); HttpSession session = request.getSession(); session.setAttribute("abc", "dbc"); ModelAndView mv = null; try { Object handler = handlerMapping.getHandler(request).getHandler(); mv = handlerAdapter.handle(request, response, handler); } catch (Exception e) { e.printStackTrace(); } Assert.assertNotNull(mv); Assert.assertEquals(response.getStatus(), 200); Assert.assertEquals(mv.getViewName(), "ccms/account"); } }
The choice of framework here is mainly for some frameworks commonly used in our system. Choosing a special testing framework has simplified our daily testing work and improved work efficiency.
last
I hope that the article will help you. If you have other questions, please welcome to come to exchange and supplement (pay attention to WeChat official account: program yuan Muzi to collect massive software testing resources (clear thinking, sometimes more important than the exact answers), share more technology and interview information, you can join qq(644956177), and there are also peers to exchange technology together.