Appium (已解决) 请问用例 (method) 之间如何管理 appium driver 实例

jack · 2015年12月28日 · 最后由 梁少 回复于 2016年01月15日 · 2299 次阅读

现象:
用 Appium 做 app 测试,两个 case 执行时都是在同一个 session 下与 server 通讯(第一个 case 执行完后调用 tearDown 方法删除了 session),第二个 case 执行时还用已经被删除的 session 与 server 通讯导致用例失败。

代码:
method.py 这个类中有两个方法供 case 调用
其中 db.select(method, id) 方法就是另外封装的一个取元素的方法

# coding=utf-8
from selenium.webdriver.common.by import By
from base.DataBase import *
from base.MyDriver import noxdriver

class MeThod:
    def __init__(self):
        self.driver = noxdriver.getDriver()

    def element(self, method, id):
        if method == "xpath":
            return self.driver.find_element(by=By.XPATH, value=db.select(method, id))
        if method == "id":
            return self.driver.find_element(by=By.ID, value=db.select(method, id))
        if method == "name":
            return self.driver.find_element(by=By.NAME, value=db.select(method, id))
        if method == "calss_name":
            return self.driver.find_element(by=By.CLASS_NAME, value=db.select(method, id))
        else:
            return None

    def loginOut(self):
        self.element("xpath", "1").click()
        try:
            el = self.element("xpath", "9").text
        except Exception:
            el = "无已登录账号"
        el0 = "18699999999"
        if el == el0:
            self.driver.tap([(150, 235)])
            self.element("xpath", "2").click()
            self.element("xpath", "3").click()
        else:
            self.element("xpath", "3").click()

method = MeThod()

case 代码 (为了测试方便,两个脚本文件使用一套代码,方法分别为 test_a, test_b 吧):

# coding=utf-8
import unittest
from base.Log import logger
from base.MeThod import method
from base.DataBase import *

class WeiDa(unittest.TestCase):
    def setUp(self):
        method.driver.implicitly_wait(6)

    def tearDown(self):
        method.driver.quit()

    def test_a(self):
        method.loginOut()
        method.element("xpath", "4").send_keys(db1.select("number", "4"))
        method.element("xpath", "5").send_keys(db1.select("number", "2"))
        method.element("xpath", "6").click()
        try:
            text = method.element("xpath", "9").text
        except Exception:
            text = None
            logger.error("脚本失败")
            self.assertIsNotNone(text, msg="没有找到账号")

if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(WeiDa)
    unittest.TextTestRunner(verbosity=2).run(suite)

执行 case 后报错信息:

分析请求后发现第二个 case 还是在用被删除的 session 通讯,所以必然报上图中的错误:

后来修改 method.py 代码在 init 位置添加接受一个参数和一个类方法:

def __init__(self, driver):
        self.driver = driver

def getDriver(self):
        return self.driver

case 这样写后能正常执行(也就是两个 case 都是独立的 session):

# coding=utf-8
import unittest
from base.MeThod import MeThod
from base.MyDriver import noxdriver

class WeiDa(unittest.TestCase):
    def setUp(self):
        self.a = MeThod(noxdriver.getDriver())
        self.a.getDriver().implicitly_wait(6)

    def tearDown(self):
        self.a.getDriver().quit()

    def test_b(self):
        self.a.element("xpath", "1").click()


if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(WeiDa)
    unittest.TextTestRunner(verbosity=2).run(suite)

但是这样调用 method 中打方法后,编辑器中不会出现属性的方法提示了,就是输入.后不跟方法了

请问怎么改写?
备注:已经解决

共收到 5 条回复 时间 点赞

额,看了几遍,有些地方没有看懂:

  1. Method 的 init 方法不是没有参数吗?最后那段代码里 Method(noxdriver.getDriver()) 是啥?
  2. 没看懂 为了测试方便,两个脚本公用一套代码 的意思,你是说这个脚本跑两次就是两个用例了?
  3. 从你的解决方案来看,就是把 driver 实例分别放到 Method 里面,让它们分开使用两个 driver ?
  4. 一开始的 Method 里面不就有个 get 方法获取 driver 嘛,为啥后面又加了个 getDriver ?

关于你最后的不会出现方法提示,我觉得这个应该和你的 element 对应的类有关吧。我感觉你前面和后面两个用例之间应该改了不少代码,但没有放出来,所以也没办法搞懂你出问题的原因。

另外,你的标题取得不好,这个不是 appium 如何管理 session(它的管理很简单,同一时间只能有一个 session ,每个 session 的生命周期就是开 (初始化)->使用->关 ( quit 或者 timeout ))。你的问题应该是用例(method)之间如何管理 appium driver 实例。管理方法应该是每个 Test suite(class)开始时开 session ,结束时关 session 。你一开始的问题应该是每个用例都不会去开 session ,但是都会关 session ,所以后面的就没 session 可用了。

#1 楼 @chenhengjie123
恩,改了下帖子
1.Method(noxdriver.getDriver()) 这个是修改后的 Method 类接受一个参数,noxdriver.getDriver() 等价于 webdriver.Remote(self.baseUrl, self.desired_caps)
2.这个意思是说两个脚本文件 case1 跟 case2 都是一样的代码
3.其实要的效果是 driver 实例都在 case 里面生成,每个 case 的 driver 实例独立互不干扰(且能调用 method 类方法)。或者 case 的 driver 实例都从 Method 来,但是能达到每次运行关闭脚本都能创建 session--关闭 session 效果。
4.这个是贴代码时贴了最后一次修改的代码,已经修改帖子部分内容
还请恒洁看看

我也碰到过,明明 quit 了下次再启动,也生成新的 session 了,但后面会用到之前的 session。
我现在是初始化的时候直接把 appium 的进程干掉,再重启

#2 楼 @x746560359 明白你的意思了。
按照你这种需求,我会写一个 test case 的基类,里面的 setUp 和 tearDown 做创建 session 和 关闭 session 的事情。剩下的 case 继承这个基类,再去做自己的事情。

至于 Method 类应该是自己生成 driver ,还是使用外部的 driver,取决于你对这个类的使用方式吧。我个人观点,除非这个类是静态类,否则这种本来生命周期和 Method 类一样的实例我会放在 Method 类里面初始化,避免代码冗余。

不过这个问题不大,按照你的需求,只要保证各个 case 间 session 独立就好。

至于你说不会出现代码提示的那个问题,你试下在 IDE 里 Ctrl 加鼠标左键点击 element(),看能不能跳转到它的类?正常来说能跳转的话这个类的方法在输入 . 后会自动显示的。

已收藏

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