Appium pytest 的 conftest fixture 和 pytest.mark.parametrize 如何协调?

醋精测试媛 · 2021年04月06日 · 最后由 醋精测试媛 回复于 2021年04月08日 · 653 次阅读

看了【 https://testerhome.com/topics/29298 】,没有看很懂😂

以及【 https://testerhome.com/topics/17292 】中使用好像是直接 scope 为 function,然后在参数中传入 driver
类似:

  @pytest.fixture()
  def driver():
      driver = webdriver.Remote(remote_url, desired_caps)
      yield driver 
     driver.quit()

def test_001(driver):
    driver.find_element(By.ID, "xxx")

如果我想要用@pytest.fixture(scope="session", autouse=True), 但是这样的话,driver 如果要返回,只能在每个用例函数的参数中添加 driver,如上所示,第一,比较麻烦,第二,可能也会影响使用@pytest.mark.parametrize,请问大家都是怎么初始化 driver 的呢?

另外,想要不写死数据,要用到参数化,如果放到 yml 文件中,数据就只能写死了,如果放到 py 文件中,数据可能是活的,但是可读性太差,这个问题有办法协调吗?

比如说 login,有密码错误和账号错误的情况,这种情况应该把账号写死吗,举个例子,手机号 13122226666,这个手机号是未注册的手机号,会提示错误,这个用例应该每次使用不同的错误的手机号吗,下次使用 15922229999 之类的。

最佳回复

账号空、密码空、账号密码都为空、账号不存在、密码错误、账号密码正确的情况,每次测试的数据应该一样吗?

llyyff 回复

我还是决定把这两个问题先解决。
针对这个需求,我想到了一个比较笨的想法,就是在 yaml 中使用 ${变量或者函数}的形式,但是我可以在 get yaml 中数据的时候,对里面符合上述形式的内容进行替换。代码如下:

def get_yaml(filepath, field):
    """
    读取yaml文件
    :param filepath: 文件路径
    :param field: yaml中的key
    :return: dict,list
    """
    with open(filepath, 'r', encoding='utf-8') as f:
        file_data = f.read()
        data = yaml.load(file_data, Loader=yaml.FullLoader)
        f.close()
    raw_data = data[field]
    # 将原生数据转为字符串类型
    string = str(raw_data)
    # 从字符串中搜索符合${函数/变量}的字符串,并将其中的函数/变量计算出来
    for expression in re.findall("(?<=\\${)[A-Za-z_][A-Za-z0-9_()^{}]+(?=})", string):
        value = str(eval(expression))
        # 将其代替其中的函数/变量
        string = string.replace(f"${{{expression}}}", value)
    return eval(string)

比较笨,而且里面的正则表达式不知道有没有囊括所有情况,但是算是一种办法。

共收到 22 条回复 时间 点赞

想要不写死数据,要用到参数化,如果放到 yml 文件中,数据就只能写死了,如果放到 py 文件中,数据可能是活的,但是可读性太差,这个问题有办法协调吗?

就像 https://testerhome.com/topics/29298
一楼提到的,直接获取 driver 时使用单例不行吗?

闲云野鹤 回复

他们也在说这个不是特别好的办法,我之前是这么做的,既然@pytest.fixture(scope="session", autouse=True)存在,我觉得应该也是可以用的。

个人感觉单例挺好的,哈哈哈,看到别人有这么做的,在 fixture 里把 driver 设置成 global (我没试过是否可以😂 😂 )

@pytest.fixture(scope='session', autouse=True)
def drivers(request):
    global driver
    if driver is None:
        driver = webdriver.Chrome()
        driver.maximize_window()

    def fn():
        driver.quit()

    request.addfinalizer(fn)
    return driver
闲云野鹤 回复

好的,我试试,谢谢您

账号空、密码空、账号密码都为空、账号不存在、密码错误、账号密码正确的情况,每次测试的数据应该一样吗?

放在 yaml 中的数据好像可以不是写死的。。类似 key:$.data 的方式,不过我不清楚别人是如何实现的。。

llyyff 回复

yaml python 好像只能有锚点和引用 即&*

我曾在社区看到过一位大佬在 yaml 中用过 key:$.data,也在别的地方看到过一次,就是 python 的,具体实现就不太清楚了。。

llyyff 回复

可以发一下链接给我吗,我查了很多资料,但是没看到类似的内容


链接找不太到了。。只找到当初的一张截图。。

yaml 中:

读取后输出:

好像是无法使用的。

我截图的这一部分作者说是借鉴了 jmeter 中函数助手的类似方法,没写该部分的源码。。具体我就不太清楚了、、、

llyyff 回复

应该是搞不出来了😭

😂 不影响使用的话就先放一下吧。。这两个问题我都是先一放的。。

llyyff 回复

我还是决定把这两个问题先解决。
针对这个需求,我想到了一个比较笨的想法,就是在 yaml 中使用 ${变量或者函数}的形式,但是我可以在 get yaml 中数据的时候,对里面符合上述形式的内容进行替换。代码如下:

def get_yaml(filepath, field):
    """
    读取yaml文件
    :param filepath: 文件路径
    :param field: yaml中的key
    :return: dict,list
    """
    with open(filepath, 'r', encoding='utf-8') as f:
        file_data = f.read()
        data = yaml.load(file_data, Loader=yaml.FullLoader)
        f.close()
    raw_data = data[field]
    # 将原生数据转为字符串类型
    string = str(raw_data)
    # 从字符串中搜索符合${函数/变量}的字符串,并将其中的函数/变量计算出来
    for expression in re.findall("(?<=\\${)[A-Za-z_][A-Za-z0-9_()^{}]+(?=})", string):
        value = str(eval(expression))
        # 将其代替其中的函数/变量
        string = string.replace(f"${{{expression}}}", value)
    return eval(string)

比较笨,而且里面的正则表达式不知道有没有囊括所有情况,但是算是一种办法。

llyyff 回复

但是还是有缺陷的,比如 yaml 中的函数必须和 get_yaml 函数在同一个 py 文件中,不然计算不出来。但是还是放到这里,期望有人可以提出其他的想法吧。

非必须在同一个 py 文件中, 你可以看下 python 的反射

driver 问题有两种比较优雅的方式。
方式一,autouse,参考代码:

class TestClass:
    @pytest.fixture(autouse=True)
    def transact(self, request, db):
        db.begin(request.function.__name__)
        yield
        db.rollback()

    def test_method1(self, db):
        assert db.intransaction == ["test_method1"]

    def test_method2(self, db):
        assert db.intransaction == ["test_method2"]

方式二,conftest,参考代码:

https://dongfanger.gitee.io/blog/pytest%E5%8E%9F%E7%94%9F%E6%A1%86%E6%9E%B6/003-%E7%B2%BE%E9%80%9Afixture.html#fixture-setup-teardown

dongfanger 回复

目前采用的是方法一,因为 fixture 有返回,所以应该无法用方法二吧。

幺叁叁 回复

好的,我看看!

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