csv技术测试框架

来源:互联网 发布:linux 找不到命令 编辑:程序博客网 时间:2024/04/24 17:50

单元测试遵守3A原则(Arrange, Act, Assert)即准备,执行,验证。

在准备测试数据时,若是使用硬编码进行new 对象,修改数据等操作。会遇到几个问题:测试数据的维护性不好,不方便管理,不够直观,数据可重用性低,对比字段多时不方便验证。因此测试数据需要从硬编码中分离出来,使用文档管理。 CSV简洁方便,二进制,支持多种格式编辑,支持excel,libreoffic编辑,数据版本易于维护。

在assert验证期间,当一个对象的属性很多时,Assert.assertEquals()过程中部分人为了麻烦,只是验证部分重要数据,这会造成验证数据的不完整性。为了避免重复这种比较操作,需要把此部分提取出来,作为模块运行。

csv测试框架实现:

csv格式(title列,必需与数据库字段相同,实体对象属性相似)

unitTest  id  account  amount

before   1  张三   20

after   1  张三 30

before测试准备数据,after执行后进行的验证数据

核心类

testDataContext:测试数据载体

public String tableName;
    public String idColumn;
    public String dbType;

    public String csvPath;
    public String csvCharset;
    
    public String[] classNameArray;
    public String[] columnNameArray;
    
    public Map<Long, Map<String, String>> beforeCsvDataTestMap;
    public Map<Long, Map<String, String>> afterCsvDataTestMap;

testDataManager:测试数据的加载维护管理

 loadTestDataCsv(String csvPath, TestDataContext dataContext) ;

 putDataToDb(QueryRunner queryRunner, TestDataContext dataContext, Long... idList) 

assertDataById(QueryRunner queryRunner, TestDataContext dataContext, ConvertMetaAndCacheKey convertMeta, boolean changeExpect, Set<String> skipAssertSet, Long... idList)

skipAssertSet:过滤不需要比较的属性字段


assertConvertManager:处理DO,csv,map之间的转换,初始化准备数据。把所有数据转换成Map对象来进行处理。

prepareCsvColumnToClassField(String table, String[] columnArray, Class<?> clazz) 初始化关联csv的列与对象属性。

Map<String, String> buildColumnToFieldMap(String[] columnArray, Map<String, Class<?>> fieldClassMap) {
        Map<String, String> columnFieldMap = new HashMap<String, String>();
        Map<String, String> fieldNameMap = new HashMap<String, String>();
        for (String field : fieldClassMap.keySet()) {
            fieldNameMap.put(field.toLowerCase(), field);
        }
        for (String column : columnArray) {
            column = column.toLowerCase();
            String columnKeyLower = StringUtils.remove(column, "_").toLowerCase();
            String fieldName = fieldNameMap.get(columnKeyLower);
            if (StringUtils.isBlank(fieldName)) {
                continue;
            }
            columnFieldMap.put(column, fieldName);
        }
        return columnFieldMap;
    }

private Map<String, Class<?>> getFieldClassMap(Class<?> clazz) {
        String className = clazz.getName();
        Map<String, Class<?>> FieldClassMap = cacheForFieldClassMap.get(className);
        if (FieldClassMap == null) {
            FieldClassMap = new HashMap<String, Class<?>>();
            BeanInfo bean = null;
            try {
                bean = Introspector.getBeanInfo(clazz, Object.class);
            } catch (IntrospectionException e) {
                log.error("{msg:'类属性转map异常',className:" + className + "}", e);
            }
            PropertyDescriptor[] props = bean.getPropertyDescriptors();
            for (PropertyDescriptor prop : props) {
                if (prop.getReadMethod() == null || prop.getWriteMethod() == null) {
                    continue;
                }
                FieldClassMap.put(prop.getName(), prop.getPropertyType());
            }
        }
        cacheForFieldClassMap.put(className, FieldClassMap);
        return FieldClassMap;
    }

public Map<String, Object> convertToAssertMapFromDO(Object obj)对象转换成Map<属性,对象属性值>

public Map<String, Object> convertToAssertMapFromCSV(Map<String, String> dataMap, String tableName, Class<?> classForDO) csv转换成Map<属性,csv值>
public <T> T buildDataObjectFromCSV(Map<String, String> dataMap, T dataObj, String tableName)

AssertUtils  assertEquals工具类

public static void assertMap(Map<String, Object> csvMap, Map<String, Object> doMap, boolean changeExpect, Set<String> skipAssertSet) {
        if (skipAssertSet == null) {
            skipAssertSet = new HashSet<>();
        }
        for (Map.Entry<String, Object> entry : csvMap.entrySet()) {
            if (skipAssertSet.contains(entry.getKey())) {
                continue;
            }
            if (!changeExpect) {
                Assert.assertEquals(entry.getKey(), entry.getValue(), doMap.get(entry.getKey()));
            } else {
                Assert.assertEquals(entry.getKey(), doMap.get(entry.getKey()), entry.getValue());
            }
        }
    }


以上是粗略代码。

MemberTest:

Arrange:

@PostConstruct
    public void init() {
        if (dataContext == null) {
            dataContext = dataManager.loadCsvDataContextToMap("/csv/member.csv", "member");
            convertManager.prepareCsvColumnToClassField(dataContext.tableName, dataContext.columnNameArray, Member.class);
        }
    }

public void test_updateAmount_增加用户金额(){

        Long id = 1L;
        dbQueryUtil.update("delete from member where id=" + id);
        dataManager.putDataToDb(dbQueryUtil, dataContext, id);

    //Act:

     //执行增加方法 

  //Assert

      testManager.assertDbById(dbQueryRunner, dataContext, dataContext.dataAfterTest, cm, id, skipFieldList);

}

整个测试方法相当简洁,没有很多重复的assertEquals,验证了所有字段,保证测试完整性。


流程:testDataManager(加载csv) --> assertConvertManager(初始化,并缓存到map) -->assertConvertManager(数据之间的转换) --> AssertUtils(转换成map,进行Assert.assertEquals)