TA的每日心情 | 擦汗 前天 09:04 |
---|
签到天数: 1047 天 连续签到: 5 天 [LV.10]测试总司令
|
2#
楼主 |
发表于 2017-9-15 14:04:56
|
只看该作者
到这里,解决了配置读取的问题,还需要解决代码运行时如何让它自己去选择正确的集群配置文件的问题。我是将选择配置文件的逻辑全部封装到了一个工厂类BaseConfigFactory.java中,在实际测试使用时,我只需要通过工厂类的静态方法BaseConfigFactory.getInstance()去获取想要的配置信息,而不需要关心它到底是如何去选择正确的配置文件的。工厂类的实现可以参考:
- public class BaseConfigFactory {
- private static final String testEnv= System.getenv("TEST_ENV") == null ? "null" : System.getenv("TEST_ENV");
- private static Logger logger = Logger.getLogger(BaseConfigFactory.class);
- private static BaseConfig baseConfig;
- private static HashMap<String, String> clusterConfigMap;
- public static synchronized BaseConfig getInstance(){
- if (null == baseConfig){
- PropertyConfigurator.configure("log4j.properties");
- initMap();
- setupConfig();
- }
- return baseConfig;
- }
-
-
- public static void initMap(){
- clusterConfigMap = new HashMap<>();
- clusterConfigMap.put("TEST-BJ", "test-bj.properties");
- clusterConfigMap.put("ONLINE-BJ", "online-bj.properties");
- clusterConfigMap.put("ONLINE-XS", "online-xs.properties");
- clusterConfigMap.put("ONLINE-LT", "online-lt.properties");
- clusterConfigMap.put("ONLINE-BEIJING", "online-beijing.properties");
- clusterConfigMap.put("ONLINE-HD", "online-hd.properties");
- clusterConfigMap.put("null", "test-local.properties");
- }
-
- public static void setupConfig(){
- logger.info("TEST ENV: " + testEnv);
- String propertyFile = clusterConfigMap.get(testEnv);
- logger.info("Using '" + propertyFile + "' as property file.");
- baseConfig = new BaseConfig(propertyFile);
- }
- }
复制代码 即,将所有的集群的配置放入到一个Map中,然后通过读取环境变量TEST_ENV的值来选取具体的集群配置文件clusterConfigMap.get(testEnv)。
3.2.3 log4j日志管理
良好的日志输出是帮助定位问题的关键环节,尤其是定位服务器上执行时出现的问题。这边贴一个log4j的配置:
- ### set log levels ###
- log4j.rootLogger = debug, stdout, D, E
- ### 输出到控制台 ###
- log4j.appender.stdout = org.apache.log4j.ConsoleAppender
- log4j.appender.stdout.Target = System.out
- log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
- log4j.appender.stdout.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss.SSS Z} %p [%c{1}] [Thread-%t] %m%n
- ### 输出到日志文件 ###
- log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
- log4j.appender.D.File = logs/console.log
- log4j.appender.D.Append = true
- ##输出Debug级别以上的日志##
- log4j.appender.D.Threshold = INFO
- log4j.appender.D.layout = org.apache.log4j.PatternLayout
- log4j.appender.D.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss.SSS Z} %p [%c{1}] [Thread-%t] %m%n
- ### 保存异常信息到单独文件 ###
- log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
- ##异常日志文件名##
- log4j.appender.E.File = logs/error.log
- log4j.appender.E.Append = true
- ##只输出ERROR级别以上的日志##
- log4j.appender.E.Threshold = ERROR
- log4j.appender.E.layout = org.apache.log4j.PatternLayout
- log4j.appender.E.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss.SSS Z} %p [%c{1}] [Thread-%t] %m%n
- ##Hibernate日志级别设置
- log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
- log4j.logger.org.hibernate=ERROR
- # Changing the log level to DEBUG will result in Hibernate generated
- # SQL to be logged.
- log4j.logger.org.hibernate.SQL=ERROR
- # Changing the log level to DEBUG will result in the PreparedStatement
- # bound variable values to be logged.
- log4j.logger.org.hibernate.type=ERROR
复制代码 该配置将INFO级别和ERROR级别的日志分别定位输出到不同的文件,且日志文件会按照日期进行自动归档,输出的格式包含了日志的日期、级别、类信息、线程信息、日志内容等。
一般情况下,对于接口测试,当接口测试用例失败时,我们要打印的日志包括:请求的url、参数、方法、实际响应、期望响应等等。
3.3 分层设计、解耦
首先看一下项目的工程目录:
可以看到,项目中包含了多个package,各个package的作用已经在图片中标示了。以前好多测试人员的习惯是将api代码的调用、测试方法的编写、data Provider的编写、测试数据的构造全部写在一个类文件中,这样做其实会有几个问题:
●可读性差
●代码复用性低
●维护性差
●难以调试
●耦合带来的其它各类问题
此外,如果不同集群的测试数据不同,会有大量的if判断,结果是灾难性的。
下面以一个用例为例,展示代码的结构:
- 测试api:
- public class ScheduleApi extends BaseAzkabanApi{
- ...
- ...
- /**
- * 使用默认公共账号、email、失败策略、sla报警邮箱新增正常调度。
- * @param projectName
- * @param flow
- * @param projectId
- * @param scheduleTime
- * @param scheduleDate
- * @param period
- * @return
- */
- public ResponseCode addNormSched(String projectName, String flow, String projectId, String scheduleTime, String scheduleDate,String period){
- return scheduleFlow(projectName, flow, projectId, scheduleTime, scheduleDate, defaultProxyUser, defaultProxyEmail, period, defaultSlaEmail);
- }
- ...
- ...
- }
复制代码 测试代码test:
- @Test(singleThreaded=true)
- public class ScheduleTest{
- ...
- ...
- /**
- * 新增正常调度
- * @param projectName
- * @param flow
- */
- @Test(priority=1, dataProvider="addNormSched", dataProviderClass=ScheduleDataProvider.class, testName="1410356")
- public void addNormSched(String projectName, String flow, String expectedStatus, String hasScheduleId, String message){
- ResponseCode rc= scheduleApi.addNormSched(projectName, flow);
- Assert.assertEquals(rc.getStatus(), expectedStatus, message+rc.getDebugInfo("返回结果中的状态status对应值"));
- Assert.assertEquals(rc.hasProperty("scheduleId"), Boolean.parseBoolean(hasScheduleId), message+rc.getDebugInfo("返回结果中是否包含scheduleId"));
- }
- ...
- ...
- }
复制代码 测试用例dataProvider:
- public class ScheduleDataProvider {
- @DataProvider(name = "addNormSched", parallel=true)
- public static Object [][] addNormSched(){
- return new Object[][]{
- ScheduleTestData.validNormSchedule,
- ScheduleTestData.notExistedProject,
- ScheduleTestData.notExistedFlow
- };
- }
- ...
- ...
- }
复制代码 测试数据testdata:
- public class ScheduleTestData extends BaseTestData{
- ...
- ...
- //Testdata for addNormSched
- public static Object[] validNormSchedule={VALID_PROJECT_NAME, VALID_NORMAL_SCHEDULE_FLOW, "success", "true", "设置有效的正常调度"};
- public static Object[] notExistedProject={NOT_EXIST_PROJECT_NAME, VALID_NORMAL_SCHEDULE_FLOW, "error", "false", "不存在的project"};
- public static Object[] notExistedFlow={VALID_PROJECT_NAME, NOT_EXIST_FLOW_NAME, "error", "fasle", "不存在的flow"};
- ...
- ...
- }
复制代码
|
|