通用技术 重构自动化 2 -- 在一套测试代码中支持多版本产品

flint · 2015年06月16日 · 最后由 pighero001 回复于 2015年06月26日 · 1971 次阅读

1. 背景
对于有些项目,需要在生产环境支持不同的版本,比如对于不同的企业级用户,或者不同国家的支持。

2. 问题
通常解决这个问题有几种方法:第一,每个版本维护一套代码,但是这样冗余代码太多,因为上下两个版本的差异可能并不大,而且如果有改变需要改动多个版本;第二,在代码中加入 if else 分之对版本进行判断,这样的结果是经过几个版本以后,项目中死代码很难清理,维护成本加大。

3. 解决办法
在这里我采用了一种插件的方式,也就是我把所有的页面、自定义元素都看成可拼装的对象,然后根据版本来自动组装成需要的页面。我们只需要维护一个版本号和加载对象的对应关系就可以了。
首先写一个拼装函数:

from distutils.version import StrictVersion  
from .elements import baseelements  

object_dir_map = {"element.base": "baseelements"}  

def get_object(env, method, module, object_name):  
    object_map = {}  
    object_module = object_dir_map[method + "." + module]  
    object_map.update(eval(object_module).object_map)  
    target_version = '1.0'  
    if module == "moduleA" or module == "base":  
        server_ver = env.moduleA_version  
    elif module == "moduleB":  
        server_ver = env.moduleB  
    object_versions = object_map[object_name]  
    for version in object_versions:  
        if StrictVersion(server_ver) >= StrictVersion(version):  
            if StrictVersion(target_version) <= StrictVersion(version):  
                target_version = version  
    if method == "page":  
        exec("from .pages." + object_module + "." + object_versions[target_version] + " import " + object_name)  
    elif method == "element":  
        exec("from .elements." + object_module + "." + object_versions[target_version] + " import " + object_name)  
    return eval(object_name)  

def get_page(env, module, page_name):  
    return get_object(env, "page", module, page_name)  

def get_element(env, module, element_name):  
    return get_object(env, "element", module, element_name)

然后需要维护一个版本的对应关系

object_map = {"LaunchPage": {"1.0": "login_page"}}

如果想获取元素或者页面我们只需要 call get_page 或者 get_element 就可以了

共收到 4 条回复 时间 点赞

感谢分享!方法很不错,确实是一个十分方便灵活的方法。但有些地方看得不是太懂,不知道你是否方便解下疑?

  1. 最后的 维护一个版本的对应关系 这个对应关系具体是在哪个位置维护?是在 case 里面吗,还是抽取出来放到一个统一的目录下,通过命令行参数选择使用哪个版本?

  2. 你在拼装函数里使用的参数 env 是起到什么作用?是保存 module 名称与 module 对象映射关系的 dictionary 吗?

  3. 如果可以的话能否举一个比较具体的例子?如有两个 version 不同对应 page 和 element 不同的项目,里面具体如何采用这种插件的方式来让用例通过版本对应关系自动选择相应的 page 和 element 对象。上次的 重构自动化 1 里面说得挺全的,但这次只给了关键代码,可能有不少人一下子看不懂。

#1 楼 @chenhengjie123 这次的确写的不够详细,我会在今天晚一点补上例子,因为写的有点着急。我先回答你前两个问题吧。

  1. object_map 是在一个单独文件中的,你看 object_dir_map 这个维护的就是这个文件所在的位置,其实这个就是一个很简单的动态加载的实现,我通过版本号找到需要加载的文件,这些文件名就在 object map 里面。但是如果把所有的对应关系放在一个文件里面我觉得会比较乱,所以我把不同的模块的对应关系放在了不同文件里,这个文件的位置就在 object_dir_map 里面维护的。
  2. env 其实就保存了所有我所需的环境变量,比如测试环境,web driver,版本号等等。

#2 楼 @flint 好的,我明白了。谢谢!

#2 楼 @flint 研发代码都进行封板操作,居然你想一个版本兼容 N 个历史版本,不得不说你有点想多了。考虑地方太多,逻辑太复杂,当心你的代码存在很多隐患和 BUG。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册