本文已参加「新人创造礼」活动,一同开启掘金创造之路。

布景

在接口自动化测验进程中,结构测验数据是必不可少的一个环节,但怎么康复测验数据也相同值得重视。业内常见的做法有:

  1. 不康复:假如是没什么影响的数据,不康复也无所谓,缺点便是会形成很多数据冗余;另外假如每次结构的都是重复数据且接口存在重复性校验,那么势必会形成接口报错、数据结构失利,然后影响到测验流程;
  2. 备份/康复整个数据库:这种做法最简略粗暴,条件是要先备份数据库,然后在履行完测验后康复数据库;这种对环境有要求,比如最好是一套独立的、可供自动化测验随便折腾的环境,假如在测验的环境还有其他人在用,那么这种做法明显不可取;
  3. 手动删去数据:能够是页面上手动删去,或者是调用独自的删去接口删去,也能够是手动删去各个数据表中的数据;
  4. 调用删去接口,形成闭环:这也是现在最常见的做法,即调用新增接口–>查询接口–>修正接口–>删去接口,然后形成一个完整的闭环,既达到了接口事务流程验证的意图,也避免了手动删去测验数据的费事;

以上几种办法中,最终一种是最便捷、也是应用最为广泛的。

自动化测试中对数据恢复的思考与实际业务改造实践

但实践中,或许部分接口的事务流程并不存在彻底闭环的情况,比如咱们某个项目有个新增企业的事务,假如依照办法4,那么调用顺序便是新增企业–>修正企业信息–>查询企业信息并断语修正字段是否收效–>删去企业。但实践项目中只要增、查、改接口,并没有删去接口(规划如此)。尤其是新增接口,先会调用一个查询接口,获取第三方数据库视图中的企业列表,拿到增加企业信息的相关字段,再调用新增接口增加到咱们体系中来,新增时会校验该企业信息是否已存在,不存在则新增,存在则回来错误码。而在没有供给删去接口的情况下,自动化测验进程中就要确保:

  • 要么每次新增的企业数据都不一致(这样就能够不必删去数据,条件是第三方视图中的数据量够大,能够确保一向新增下去);
  • 要么每次新增完数据再履行SQL句子逐个删去相关数据表中新增企业时产生的数据(这样就相当于曲线救国式地完成了事务闭环,由于即使是供给了删去接口,其背面也是履行相关SQL进行删去各个数据表数据的操作)。留意这儿不能是手动删去数据,无论是手动从页面删去仍是手动从数据库删去。由于假如运转一次就删去一次,那运转一百次就要手动删去一百次,明显不切实践,这样也与咱们自动化的理念背道而驰。

之前咱们组小伙伴所写的自动化测验用例中,运用的是上述第一种办法,即每次新增不一样的企业数据,新增后不删去(原因是开发没有供给删去接口,SQL句子触及的表较多,且表与表之间存在许多相关,刚好视图中的数据够多,能够一向增加下去,只要确保每次增加的数据不一致就能够了)。这样的完成办法也不是不能够,仅仅会带来许多坏处,当今天文章所表述的内容,便是对该完成办法进行优缺点剖析,并依据第二种履行SQL删去数据的完成办法进行改造。

一、剖析利弊

1.原完成办法

上述布景中现已说到视图中的数据够多,能够一向增加下去,只需确保每次增加的数据不一致即可。增加企业数据前会先调用查询接口,读取第三方企业数据列表,那么就需要规划一种办法使每次读取到的企业数据不一致。原完成办法如下:

① 界说读取和写入ini装备文件的办法

装备文件内容如下:

[company_data]
x = 1  # page
y = 1000  # page_size
next_y = 242  # index
[product_data]
x = 1
y = 1000
next_y = 146

读写装备文件办法如下:

import configparser, os
def get_next_data(ini_name):
    """
    ini_name:装备文件中,装备的名字,写在[]里面的那串
    办法回来列表,按顺序分别是  x,y,next_y
    对应的意思是  当时要恳求的页码,当时恳求的条数,当时从第几条获取
    """
    # 取文件途径
    path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    # 组成装备文件的途径
    ini_path = path + '/config/page_config.ini'
    cf = configparser.ConfigParser()
    cf.read(ini_path)
    # 取上一次恳求的页码
    x = int(cf.get(ini_name, 'x'))
    y = int(cf.get(ini_name, 'y'))
    next_y = int(cf.get(ini_name, 'next_y'))
    if next_y + 1 < y:
        # 假如+1还小于当时页码数据,那么下次还在当时页数据
        cf.set(ini_name, 'next_y', str(next_y + 1))
    else:
        # 假如+1等于当时页码数据,那么下次就翻页,x也要+1
        cf.set(ini_name, 'x', str(x + 1))
        cf.set(ini_name, 'next_y', str(0))
    cf.write(open(ini_path, 'w'))
    return [x, y, next_y]

在上述办法中,会先读取ini文件中的x、y和next_y,也便是page、page_size、index,如x=1,y=1000,next_y=242 作为入参传给查询接口,x标明恳求第1页,y标明每页1000条,next_y则作为索引值、提取这1000条数据中的第242条数据

② 测验用例中调用该办法,读写装备文件

import api_test.config.page_config as page_config
@pytest.mark.rs_smoke
@allure.story("企业办理")
def test_company_manager(self, rs_resource, rs_admin_login, rs_get_admin_user_info, use_db):
    """测验企业增改查接口"""
    user_id = rs_admin_login
    cpy_id = rs_get_admin_user_info
    # 调用办法获取前次读取的方位
    config_data = page_config.get_next_data("company_data")
    x = config_data[0]
    y = config_data[1]
    next_y = config_data[2]
    get_company_list = rs_resource.get_company_list(cpy_id, user_id, x, y)
    company_list = get_company_list["d"]
    company_name = company_list[next_y]["a"]
    company_simple = company_list[next_y]["a"]
    company_num = company_list[next_y]["d"]
    company_manager = self.fake.name()
    company_phone = self.fake.phone_number()
    company_pwd = 123456
    company_type = 3
    sort_id = str(random.randint(1, 100))
    try:
        with allure.step("调用增加企业接口"):
            add_company = rs_resource.add_company(cpy_id, user_id, company_name, company_manager, company_phone,
                                                  company_pwd, company_simple, company_num, company_type)
            # 当错误码回来254,说明该企业信息已存在
            # 此刻再调用get_next_data办法,next_y +1
            while add_company["a"] == 254:
                config_data = page_config.get_next_data("company_data")
                x = config_data[0]
                y = config_data[1]
                next_y = config_data[2]
                get_company_list = rs_resource.get_company_list(cpy_id, user_id, x, y)
                company_list = get_company_list["d"]
                company_name = company_list[next_y]["a"]
                company_simple = company_list[next_y]["a"]
                company_num = company_list[next_y]["d"]
                add_company = rs_resource.add_company(cpy_id, user_id, company_name, company_manager, company_phone,
                                                      company_pwd, company_simple, company_num, company_type)
        assert add_company["a"] == 200
        self.company_user_id = add_company["d"]
        select_db = use_db.execute_sql(
            f"SELECT * FROM t_r_company_base WHERE user_id = {self.company_user_id}")  # 查询数据库是否存在新增的数据
        assert company_name in str(select_db)

从上面的测验用例能够看出:

  1. 测验用例会先调用读取ini装备文件的办法get_next_data,读取到的装备为x=1、y=1000和next_y=242
  2. 将装备作为参数传递给get_company_list接口,获取企业列表并提取第242条数据
  3. 将第242条数据相关字段值传递给add_company新增企业接口,若code为200标明新增成功,若回来的code码是254,则标明企业信息已存在
  4. 当企业信息已存在时,再次调用读取装备文件办法get_next_data,更改ini装备文件、使next_y+1,提取第243条数据,并继续新增企业,断语回来值,以此循环,直到拿到的是不重复的数据、新增企业成功
  5. 最终查询数据库,断语回来值中的企业ID与数据库查到的是否一致

2.优缺点剖析

在真实回归测验进程中,上述计划是能够正常运转的,但也面对许多问题,下面深入剖析该规划的优缺点:

长处

  • 方便,运转完了,产生的数据能够不必处理,整个进程无需人工干预;

缺点

  • 形成很多数据冗余:由于运转后的数据放任不管,假如运转1000次,那么数据表中就会产生1000条企业数据和相关相关数据,假如次数更多,冗余数据必定会更多,也会给前端页面的运用形成必定的压力;
  • 运转次数有上限:由于是经过装备文件,不断读取第三方视图中的企业数据,然后增加这些企业数据到咱们的体系中,尽管现在三方企业数据量较多,大概有一万多条,但总有用完的一天,假如运转一万次,最终一页的最终一条也被增加过了,就会达到数据量上限,那么再次运转必定会形成数据重复、增加失利;
  • 调试不方便、履行功率:我一向比较倾向于装备写在py文件中,而不是yaml或ini文件中,这样就能够不必再界说一个独自的办法来读取装备,然后减小层层调用而导致的犯错概率。不过这个不是重点,重点是会形成履行功率慢的问题,由于咱们组内代码是同步到gitlab的,装备文件也包含在内。但假如其间A人员履行了50次,next_y会从242自增到292并写入装备文件,而B人员此刻没有更新代码,装备文件的next_y仍旧为242,那么他履行时前50次都会重复,由于那50条数据现已被用过了,直到next_y自增到293条数据才能运用,这50条while循环读写产生的时刻便是浪费的时刻,假如中心相差的次数更多500乃至5000次,那么履行功率就会更加低下;
  • 装备文件不统一,git办理不方便:试想一下,每履行一次测验用例,装备文件(nexy_y)就会产生改变一次,git文件状态也就改变一次,也就意味着每履行一次就要提交一次代码!或许你会说不提交便是了,那假如A、B两个测验人员的代码长期不统一,就会堕入上一个问题中由装备文件长时刻不同步而形成的履行功率低下的因果循环中去;

说了这么多,总结下来便是:装备文件假如提交,就意味着每次都要提交,然后每个人在履行前git pull一次、履行完了git push一次;不提交的话就意味着每个人的装备文件不一样,其间一个人运转的次数越多,其他人运转的功率就越低。好吧,的确挺痛苦。说到底仍是规划模式的问题,装备文件在git办理下不能容易产生变动,运转结果的好坏更不能严峻依靠装备文件!

二、改造进程

已然面对那么多问题,那就只要改造了,俗话说“不破不立”!写代码,不只要确保代码能运转起来,还要从各个方面确保代码的健壮性。规划产品和规划测验用例也是一样。以下是整体事务剖析和测验用例改造进程:

1.日志剖析

早在开始之初就听说增加企业这个接口触及的表查询、刺进特别多,会产生许多的事务相关数据,处理起来也会比较费事,今天一试,果然如此。

开发没有供给删去接口,但有新增接口,假如我能找到新增企业时刺进了哪些数据,再反向将这些数据逐个删去,不也就相当于完成了删去接口的功能了吗?说干就干,先剖析接口日志(进程的确比较长,核心思维便是:依据后台日志一点一滴整理数据的流向,刺进了哪张表、哪些数据,并找出数据表中的唯一能代表该条数据的字段值,如ID、手机号等,以便于后边规划删去该条数据的SQL句子):

接口恳求及参数

我一遍手动新增一个企业,一遍调查后台日志。在新增企业接口恳求及回来的打印日志如下:

自动化测试中对数据恢复的思考与实际业务改造实践

查询手机号

自动化测试中对数据恢复的思考与实际业务改造实践

在刺进账户表前,会先调用一个c.f.r.m.AccountMapper.queryUserPhone的办法,查询数据库中是否存在相同的手机号,不存在则回来0,只要回来数据为0 ,才会履行后续的刺进数据操作

调用注册接口

假如手机号不重复,则会调用注册接口,成功后回来数据:respContent: 473036,即用户的user_id

自动化测试中对数据恢复的思考与实际业务改造实践

后边便是调用注册接口后一系列的相关表查询和写入数据了

t_r_user_info 表写数据

自动化测试中对数据恢复的思考与实际业务改造实践

insert into t_r_user_info ( user_id, user_name, phone, `status`, product_id, create_time ) values ( 473036, 浙江华甸, 13912300000, 1, 2022, 1667443614864 )

查看数据表,数据用户信息数据现已写入,由于手机号是唯一的,所以能够依据手机号删去本表对应数据

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_account 账户表写数据

自动化测试中对数据恢复的思考与实际业务改造实践

select user_id, account_name, pass_word, `status`, product_id, create_time, update_time, ext1, ext2, ext3 from t_r_account where account_name = 13912300000 and product_id = 2022 and status = 1 limit 1

查看数据表,账户数据现已写入,统一也能够依据手机号删去本表对应数据

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_post 岗位表查询数据

自动化测试中对数据恢复的思考与实际业务改造实践

select id, company_id, post_code, post_name, remark, `status`, creator, create_time, ext1, ext2, ext3,classify from t_r_post where post_code = 16 and company_id = 0 order by status DESC limit 1

查询post_code为16,company_id为0的这条数据

自动化测试中对数据恢复的思考与实际业务改造实践

由于是查询操作,所以无需复原数据

t_r_user_post 人员岗位表写数据

自动化测试中对数据恢复的思考与实际业务改造实践

insert into t_r_user_post ( user_id, post_id, post_code, post_name, creator, create_time ) values ( 473036, 4, 16, 客商调度, 429381, 1667443614864 )

刺进后的数据如下,能够依据id和user_id来删去本条数据

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_post 岗位表查询数据

自动化测试中对数据恢复的思考与实际业务改造实践

select id, company_id, post_code, post_name, remark, `status`, creator, create_time, ext1, ext2, ext3,classify from t_r_post where post_code = 17 and company_id = 0 order by status DESC limit 1

查询到的数据如下:

自动化测试中对数据恢复的思考与实际业务改造实践

由于是查询操作,所以无需复原数据

t_r_user_post 人员岗位表写数据

自动化测试中对数据恢复的思考与实际业务改造实践

insert into t_r_user_post ( user_id, post_id, post_code, post_name, creator, create_time ) values ( 473036, 7, 17, 客商办理员, 429381, 1667443614864 )

刺进数据如下:

自动化测试中对数据恢复的思考与实际业务改造实践

其实稍微调查一下就能够发现,t_r_user_post表写了两次数据,也便是刺进了两条user_id为473036的数据(由于新增的用户会默许一起存在两个角色,因而本表会刺进两条数据,一个岗位ID为16-客商调度,一个岗位ID为17-客商办理员)。所以能够依据user_id删去对应数据

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_user_company 人员客商联系表写入数据

自动化测试中对数据恢复的思考与实际业务改造实践

insert into t_r_user_company(user_id, cpy_id, type, create_time, creator_id, updater_id, update_time, ext1, ext2, ext3,company_id) values (473036, 10306, 2, 1667443614864, 429381, null, null, null, null, null,10306)

刺进数据如下,能够依据user_id删去对应数据

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_company_extend 企业扩展表写数据

自动化测试中对数据恢复的思考与实际业务改造实践

insert into t_r_company_extend (company_id, ext_name, ext_code, ext_value, create_time) values (10306, 简称,cpySimpleName, 浙江华甸防雷科技, 1667443614864) , (10306, 企业编码,cpyCode, xchdfl, 1667443614864)

依据日志和SQL句子能够得知,刺进了两条数据,刺进的数据如下图所示。后续能够依据cpy_id删去本表对应数据

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_location 坐标表写入数据

自动化测试中对数据恢复的思考与实际业务改造实践

insert into t_r_location ( company_id, `name`, addr, addr_detail, addr_point, `status`, contact_company, contact_name, contact_phone, user_id, create_time ) values ( 10306, 浙江华甸防雷科技, 山西省-长治市-襄垣县, 山西省长治市襄垣县古韩镇山西机电职业技术学院(东湖校区), 113.065637,36.542198, 1, 浙江华甸防雷科技股份有限公司(String), 浙江华甸, 13912300000, 473036, 1667443614864 )

刺进数据如下,后续能够依据company_id删去记载表中的数据

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_location与t_r_company_base 坐标表与企业基础表连表查询数据

自动化测试中对数据恢复的思考与实际业务改造实践

select l.id, l.company_id, l.`name`, l.addr, l.addr_detail, l.addr_point, l.`status`, l.contact_company, l.contact_name, l.contact_phone, l.user_id, l.create_time from t_r_location l left join t_r_company_base b on l.company_id = b.id where b.ext1 = 1 and b.status = 1

查询到的数据如下:

自动化测试中对数据恢复的思考与实际业务改造实践

由于是查询操作,所以无需复原数据

t_r_transport_line 运输线路表中刺进数据

自动化测试中对数据恢复的思考与实际业务改造实践

insert into t_r_transport_line ( company_id, `name`, load_location_id, unload_location_id, create_time, creator_user_id ) values ( 10306, 旭阳煤化工的简称2-浙江华甸防雷科技, 10000, 10306, 1667443614864, 429381 )

刺进数据如下,由于线路是双向的,所以有两条数据。后续能够依据company_id删去数据

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_transport_line_point 线路途经点信息表写入数据

自动化测试中对数据恢复的思考与实际业务改造实践

insert into t_r_transport_line_point(line_id, location, sort, type, status, remark, create_time, creator_id, updater_id, update_time, ext1, ext2, ext3) values (10610, 113.065637,36.542198, 1, 1, 1, 山西省长治市襄垣县古韩镇山西机电职业技术学院(东湖校区), 1667443614864, 429381, null, null, null, null, null) , (10610, 118.92252,40.410167, 0, 1, 1, 河北省秦皇岛市青龙满族自治县青龙镇小楸子沟门, 1667443614864, 429381, null, null, null, null, null) , (10611, 113.065637,36.542198, 0, 1, 1, 山西省长治市襄垣县古韩镇山西机电职业技术学院(东湖校区), 1667443614864, 429381, null, null, null, null, null) , (10611, 118.92252,40.410167, 1, 1, 1, 河北省秦皇岛市青龙满族自治县青龙镇小楸子沟门, 1667443614864, 429381, null, null, null, null, null)

依据日志和SQL句子能够得知,刺进了4条数据,刺进的数据如下图所示

自动化测试中对数据恢复的思考与实际业务改造实践

这儿数据删去比较费事,这儿要先从t_r_transport_line表中依据company_id查到id,该id也便是t_r_transport_line_point表中的line_id,再依据line_id进行删去。

履行指定完成类

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_orgination 安排表写入数据

自动化测试中对数据恢复的思考与实际业务改造实践

总共履行5条insert操作

insert into t_r_orgination ( code, `name`, parent_id, `type`, company_id, product_id, create_time ) values ( 10306, 浙江华甸防雷科技股份有限公司, 0, 1, 10306, 2022, 1667443614864 )
insert into t_r_orgination ( `name`, parent_id, `type`, company_id, product_id, create_time ) values ( 运输中心, 13442, 2, 10306, 2022, 1667443614898 ) 
insert into t_r_orgination ( `name`, parent_id, `type`, company_id, product_id, create_time ) values ( 司机, 13443, 2, 10306, 2022, 1667443614898 ) 
insert into t_r_orgination ( `name`, parent_id, `type`, company_id, product_id, create_time ) values ( 押运员, 13443, 2, 10306, 2022, 1667443614898 ) 
insert into t_r_orgination ( code, `name`, parent_id, `type`, company_id, product_id, create_time ) values ( 473036, 浙江华甸, 13442, 3, 10306, 2022, 1667443614864 ) 

总共刺进了5条数据,后续能够依据company_id删去对应数据

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_orgination 安排表查询数据

自动化测试中对数据恢复的思考与实际业务改造实践

select id, code, `name`, parent_id, `type`, company_id, product_id, create_time, update_time, ext1, ext2, ext3,person_count,im_group_id from t_r_orgination where id = 13442

自动化测试中对数据恢复的思考与实际业务改造实践

由于是查询操作,所以无需复原数据

t_r_orgination 安排表更新数据

自动化测试中对数据恢复的思考与实际业务改造实践

update t_r_orgination SET code = 10306, `name` = 浙江华甸防雷科技股份有限公司, parent_id = 0, `type` = 1, company_id = 10306, product_id = 2022, create_time = 1667443614864, person_count = 1, im_group_id = 0 where id = 13442

t_r_orgination 表查询数据

自动化测试中对数据恢复的思考与实际业务改造实践

select id, code, `name`, parent_id, `type`, company_id, product_id, create_time, update_time, ext1, ext2, ext3,person_count,im_group_id from t_r_orgination where id = 0

从日志能够看出,没查到任何数据

t_r_res_sum_total 材料计算表刺进数据

insert into t_r_res_sum_total (company_id, `type`, kind, kind_name, total, create_time, update_time, ext1, ext2, ext3) values (10306, 1, 1, 客户数量, 0, 1667443614902, null, null, null, null) , (10306, 2, 1, 重视数量, 0, 1667443614902, null, null, null, null) , (10306, 3, 1, 产品数量, 0, 1667443614902, null, null, null, null) , (10306, 4, 1, 线路数量, 0, 1667443614902, null, null, null, null) , (10306, 5, 1, 地址数量, 0, 1667443614902, null, null, null, null) , (10306(, 6, 1, 运力数量, 0, 1667443614902, null, null, null, null) , (10306, 7, 1, 司机数量, 0, 1667443614902, null, null, null, null) , (10306, 8, 1, 押运员数量, 0), 1667443614902, null, null, null, null) , (10306, 9, 1, 车头数量, 0, 1667443614902, null, null, null, null) , (10306, 10, 1, 挂车数量, 0, 1667443614902, null, null, null, null)

总共刺进了10条数据,后续能够依据company_id删去数据

自动化测试中对数据恢复的思考与实际业务改造实践

t_o_product 表查询数据

自动化测试中对数据恢复的思考与实际业务改造实践

经过日志能够看出,没有任何参数,所以未查出数据

完毕 履行公共完成类

自动化测试中对数据恢复的思考与实际业务改造实践

调用操作日志记载接口

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_operator_log 操作日志表写入数据

insert into t_r_operator_log ( order_id, code, `type`, remark, company_id, user_id, create_time ) values ( 473036, PR001, 1, 【企业注册】手机号:13912300000 用户Id:473036, 10000, 429381, 1667443614908 )

刺进数据如下,后续能够依据company_id删去数据

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_orgination 安排表查询数据

自动化测试中对数据恢复的思考与实际业务改造实践

Preparing: select id, code, `name`, parent_id, `type`, company_id, product_id, create_time, update_time, ext1, ext2, ext3,person_count,im_group_id from t_r_orgination WHERE company_id = 10306 and code = 10306 and `type` = 1 order by create_time desc,id desc limit 1

t_r_orgination 安排表更新数据

自动化测试中对数据恢复的思考与实际业务改造实践

update t_r_orgination SET code = 10306, `name` = 浙江华甸防雷科技股份有限公司, parent_id = 0, `type` = 1, company_id = 10306, product_id = 2022, create_time = 1667443614864, update_time = 1667443614915, person_count = 1, im_group_id = 111150 where id = 13442

更新数据如下,后续能够依据company_id删去数据

自动化测试中对数据恢复的思考与实际业务改造实践

t_r_qualification_alert_config 资质告警材料装备表刺进数据

自动化测试中对数据恢复的思考与实际业务改造实践

总共刺进了21条数据,刺进数据如下,后续能够依据company_id删去数据

自动化测试中对数据恢复的思考与实际业务改造实践

2.规划删去战略

从上述的日志剖析进程能够看出,增加企业这个动作,总共触及了15张数据表的查询、刺进、更新和删去操作,其间14张表触及到数据刺进。查询就不管了,只剖析哪几张表写入了哪些数据以及怎么删去即可。经过整理总结,得出:

  • t_r_company_base 表写入1条数据,可依据phone_number查询到id和user_id,这一步最要害,这个id实践便是其他数据表所用到的company_id,可经过phone_number删去;
  • t_r_user_info 表写入1条数据,可经过user_id删去;
  • t_r_account 表写入1条数据,可经过user_id删去;
  • t_r_user_post 表写入2条数据,可经过user_id删去;
  • t_r_user_company 表写入1条数据,可经过company_id删去;
  • t_r_msds_company 表写入1条数据,可经过code(company_id)删去;
  • t_r_company_extend 表写入2条数据,可经过company_id删去;
  • t_r_orgination 表共写入5条数据,可经过company_id删去;
  • t_r_location 表写入1条数据,可经过company_id删去;
  • t_r_transport_line 表写入2条数据,可经过company_id删去;
  • t_r_res_sum_total 表共写入10条数据,可经过company_id删去;
  • t_r_operator_log 表写入1条数据,可经过company_id删去;
  • t_r_qualification_alert_config 表共写入21条数据,可经过company_id删去;
  • t_r_transport_line_point 表共写入4条数据,这个处理稍微繁琐一点,先从t_r_transport_line表中依据company_id查到id,该id也便是t_r_transport_line_point表中的line_id,再依据line_id进行删去;

3.编写删去数据的SQL句子

SQL句子如下,将其直接封装到一个静态办法delete_company_data中,直接在测验用例中调用即可,这样做的好处是:

  1. 能够避免测验用例代码较多,只需调用该办法、传入一个企业联系人手机号和一个数据库实例;
  2. 即使后边增加企业接口产生改变,产生了更多相关数据,也只需修正本办法,而无需修正测验用例;
@staticmethod
def delete_company_data(use_db, phone_number):
    """
    删去新增企业产生的相关数据
    :param use_db: 数据库实例
    :param phone_number: 企业联系人手机号
    :return:
    """
    # 查询企业ID
    select_add_company_id = f"SELECT id FROM t_r_company_base WHERE `contact_phone`={phone_number};"
    # 查询用户ID
    select_add_user_id = f"SELECT user_id FROM t_r_company_base WHERE `contact_phone`={phone_number};"
    add_company_id = use_db.execute_sql(select_add_company_id)[0]
    add_user_id = use_db.execute_sql(select_add_user_id)[0]
    # 查询线路ID
    select_line_id = f"SELECT id FROM t_r_transport_line WHERE `company_id`={add_company_id};"
    line_ids = use_db.execute_sql(is_fetchall=True, sql=select_line_id)
    line_id_1 = line_ids[0][0]
    line_id_2 = line_ids[1][0]
    # 依据company_id删去资质告警材料装备
    delete_sql_1 = f"DELETE FROM t_r_qualification_alert_config WHERE company_id={add_company_id};"
    # 依据company_id删去安排表相关数据
    delete_sql_2 = f"DELETE FROM t_r_orgination WHERE company_id={add_company_id};"
    # 依据company_id删去操作日志
    delete_sql_3 = f"DELETE FROM t_r_operator_log WHERE company_id={add_company_id};"
    # 依据company_id删去操作材料计算
    delete_sql_4 = f"DELETE FROM t_r_res_sum_total WHERE company_id={add_company_id};"
    # 删去途经点信息
    delete_sql_5 = f"DELETE FROM t_r_transport_line_point WHERE line_id={line_id_1} or line_id={line_id_2};"
    # 删去运输线路表数据
    delete_sql_6 = f"DELETE FROM t_r_transport_line WHERE company_id={add_company_id};"
    # 删去坐标表数据
    delete_sql_7 = f"DELETE FROM t_r_location WHERE company_id={add_company_id};"
    # 删去企业扩展表数据
    delete_sql_8 = f"DELETE FROM t_r_company_extend WHERE company_id={add_company_id};"
    # 删去人员客商联系表数据
    delete_sql_9 = f"DELETE FROM t_r_user_company WHERE company_id={add_company_id};"
    # 删去人员岗位表数据
    delete_sql_10 = f"DELETE FROM t_r_user_post WHERE user_id={add_user_id};"
    # 删去账户表数据
    delete_sql_11 = f"DELETE FROM t_r_account WHERE user_id={add_user_id};"
    # 删去用户信息表数据
    delete_sql_12 = f"DELETE FROM t_r_user_info WHERE user_id={add_user_id};"
    # 删去企业物料绑定联系数据
    delete_sql_13 = f"DELETE FROM t_r_msds_company WHERE code={add_company_id};"
    # 删去企业基础表数据
    delete_sql_14 = f"DELETE FROM t_r_company_base WHERE id={add_company_id};"
    # 履行各个SQL
    use_db.execute_sql(delete_sql_1)
    use_db.execute_sql(delete_sql_2)
    use_db.execute_sql(delete_sql_3)
    use_db.execute_sql(delete_sql_4)
    use_db.execute_sql(delete_sql_5)
    use_db.execute_sql(delete_sql_6)
    use_db.execute_sql(delete_sql_7)
    use_db.execute_sql(delete_sql_8)
    use_db.execute_sql(delete_sql_9)
    use_db.execute_sql(delete_sql_10)
    use_db.execute_sql(delete_sql_11)
    use_db.execute_sql(delete_sql_12)
    use_db.execute_sql(delete_sql_13)
    use_db.execute_sql(delete_sql_14)

4.本地调试

前面查询日志进程中现已手动增加了一个企业,手机号为13213213132,这儿来验证上面界说的删去战略能否成功删去数据。直接在测验用例类中新增一条用例,引用删去数据办法,履行SQL。

def test_1111(self, use_db, rs_resource):
    rs_resource.delete_company_data(use_db=use_db, phone_number=13213213132)

履行结果如下,不过这个办法并没有界说履行SQL后打印任何内容,所以在履行完成后仅仅正常运转没报错,看不出来是否成功删去了数据,后边还存在优化空间。

自动化测试中对数据恢复的思考与实际业务改造实践

我经过手动查询各个数据表,确认各个相关数据均已删去。再次挑选同一条企业数据进行新增时,仍然能新增成功。

自动化测试中对数据恢复的思考与实际业务改造实践

5.改造测验用例

本地调试经过后,即可改造测验用例中的逻辑。改造内容如下:

@pytest.mark.rs_smoke
@allure.story("企业办理")
def test_06_company_manager(self, rs_resource, rs_admin_login, rs_get_admin_user_info, use_db):
    """测验企业增改查接口"""
    user_id = rs_admin_login
    cpy_id = rs_get_admin_user_info
    # 此处去除读取ini装备文件逻辑
    # 随便传入一个页码,就算每次都从这一页开始,后边也会删去数据,不会导致数据重复
    page = 120
    get_company_list = rs_resource.get_company_list(cpy_id, user_id, page, 10)
    company_list = get_company_list["d"]
    company_name = company_list[0]["a"]
    company_simple = company_name[0:5]
    company_num = company_list[0]["d"]
    company_manager = self.fake.name()
    company_phone = self.fake.phone_number()
    company_pwd = 123456
    company_type = 3
    sort_id = str(random.randint(1, 100))
    try:
        logger.info(f"新增企业'{company_name}'信息...")
        with allure.step("调用增加企业接口"):
            add_company = rs_resource.add_company(cpy_id, user_id, company_name, company_manager, company_phone,
                                                  company_pwd, company_simple, company_num, company_type)
            while add_company["a"] == 254:
                # 以防万一,仍是加入了页码自增+1逻辑,避免这一页的数据被手动用过
                page = page + 1
                get_company_list = rs_resource.get_company_list(cpy_id, user_id, page, 10)
                company_list = get_company_list["d"]
                company_name = company_list[0]["a"]
                company_simple = company_name[0:5]
                company_num = company_list[0]["d"]
                add_company = rs_resource.add_company(cpy_id, user_id, company_name, company_manager, company_phone,
                                                      company_pwd, company_simple, company_num, company_type)
        assert add_company["a"] == 200
        self.company_user_id = add_company["d"]
        select_db = use_db.execute_sql(
            f"SELECT * FROM t_r_company_base WHERE user_id = {self.company_user_id}")  # 查询数据库是否存在新增的数据
        assert company_name in str(select_db)
        logger.info(f"企业'{company_name}'新增信息成功")
        logger.info(f"修正企业'{company_name}'信息...")
        with allure.step("调用修正企业信息接口"):
            select_db = use_db.execute_sql(
                f"SELECT id FROM t_r_company_base WHERE user_id = {self.company_user_id}")  # 查询新增的数据的id
            self.company_id = int(select_db[0])
            modify_company = rs_resource.modify_company(cpy_id, user_id, self.company_id, company_name,
                                                        company_simple, company_manager)
        assert modify_company["a"] == 200
        logger.info(f"修正企业'{company_name}'信息成功")
        logger.info(f"修正企业'{company_name}'账号...")
        with allure.step("调用修正企业账号接口"):
            company_new_phone = self.fake.phone_number()
            modify_company_phone = rs_resource.modify_company_phone(cpy_id, user_id, self.company_user_id,
                                                                    self.company_id, company_new_phone)
        assert modify_company_phone["a"] == 200
        logger.info(f"修正企业'{company_name}'账号成功")
        logger.info(f"修正企业'{company_name}'暗码...")
        with allure.step("调用修正企业暗码接口"):
            modify_company_pwd = rs_resource.modify_company_pwd(cpy_id, user_id, self.company_user_id,
                                                                self.company_id, company_new_phone,
                                                                company_pwd='654321')
        assert modify_company_pwd["a"] == 200
        logger.info(f"修正企业'{company_name}'暗码成功")
        logger.info(f"修正企业'{company_name}'排序...")
        with allure.step("调用修正企业排序接口"):
            modify_company_sort = rs_resource.modify_company_sort(cpy_id, user_id, self.company_id, sort_id)
        assert modify_company_sort["a"] == 200
        logger.info(f"修正企业'{company_name}'排序成功")
        logger.info(f"查询企业'{company_name}'信息...")
        with allure.step("调用查询企业信息接口"):
            query_company = rs_resource.query_company(cpy_id, user_id, company_num, company_type)
        assert query_company["a"] == 200
        logger.info(f"查询企业'{company_name}'信息成功")
        logger.info(f"给企业'{company_name}'绑定物料...")
        with allure.step("调用企业绑定物料接口"):
            get_exist_product_list = rs_resource.get_exist_product_list(cpy_id, user_id, x=1, y=1000)
            exist_product_list = get_exist_product_list["d"]
            exist_productID_list = []
            for i in exist_product_list:
                aa = i["aa"]
                exist_productID_list.append(aa)
            exist_product_id = random.choice(exist_productID_list)
            add_company_product = rs_resource.add_company_product(cpy_id, user_id, self.company_id, company_type,
                                                                  exist_product_id)
        assert add_company_product["a"] == 200
        select_db = use_db.execute_sql(
            f"SELECT * FROM t_r_msds_company WHERE code = {self.company_id}")  # 查询数据库是否存在新增的数据
        assert str(exist_product_id) in str(select_db)
        logger.info(f"企业'{self.company_id}'和物料的绑定联系成功")
        logger.info("删去新增企业产生的相关数据")
        rs_resource.delete_company_data(use_db=use_db, phone_number=company_new_phone)
    except AssertionError as e:
        logger.info(f"企业'{company_name}'增改查失利")
        raise e

6.运转测验

测验用例运转经过,改造完成。

自动化测试中对数据恢复的思考与实际业务改造实践

总结

以上便是结合实践自动化测验案例,对数据康复的思考和改造实践。下面简略总结一下此次改造进程中的一些心得:

  • 装备文件最好写在py文件中,避免独自界说一个办法来读取ini、yml等装备文件,然后加大犯错概率;
  • 装备文件最好不经常变动,更不要在履行进程中更改(写入)装备文件,避免带来git协一起的重复提交问题;
  • 自动化测验规划与编码完成相同重要,不只要确保事务流程能正常运转,还要确保规划的合理性和健壮性;
  • 测验人员不只要熟悉体系事务流程,还要熟悉后台完成流程,即一个手动操作或接口履行的背面究竟做了哪些动作,如履行了哪些类的哪些办法,查询、写入、更新、删去了哪些表的哪些数据,这个进程能够经过阅览开发代码和后台日志查看和整理;
  • 不要怕费事,越是杂乱的地方或许越会有不一样的收获,比如我本来以为新增一个企业便是刺进一两张表、几条数据这么简略,但实践上它背面触及了十几张表的相关查询、刺进、更新和删去;

当然,以上并不必定便是最优的规划,还存在许多优化空间,假如你有更好的计划,欢迎留言交流!