Appium [已解决] 如何才能运行脚本不用每次重新登录,一次性跑完所有的 case

· 2015年05月12日 · 最后由 119 回复于 2018年06月19日 · 1815 次阅读

大家好,现在有个情况是这样的,我在写公司 app 的脚本。之前我用 monkeyrunner 实现了基本的流程,脚本是一次性跑完所有的 case 的。
但是我学了 appium 后,写了个脚本,发现脚本每次运行一个函数都会调用 setup() 里的登录功能。。。也就是说,我每次运行脚本里的一个函数,我都会点击 home 键后重新登录。
我现在想跟 monkeyrunner 一样,登录操作只做一次,然后按照顺序运行脚本里的函数
我的脚本代码如下~当然测试报告是 ok 的

#coding=utf-8

import os
import unittest,sys,time,re,datetime,HTMLTestRunner
from appium import webdriver
from time import sleep
from appium.common.exceptions import NoSuchContextException
import sys

#reload(sys)
#sys.setdefaultencoding("utf-8") 

# Returns abs path relative to this file and not cwd
PATH = lambda p: os.path.abspath(
    os.path.join(os.path.dirname(__file__), p)
)

class ContactsAndroidTests(unittest.TestCase):
    def setUp(self):
        desired_caps = {}
        desired_caps['platformName'] = 'Android'
        desired_caps['platformVersion'] = '4.3'
        desired_caps['deviceName'] = '192.168.56.101:5555'
        '''desired_caps['app'] = PATH(
            '../../../sample-code/apps/ContactManager/ContactManager.apk'
        )'''
        desired_caps['appPackage'] = 'com.jiudao.ccare'
        desired_caps['appActivity'] = '.StartActivity'
        desired_caps["unicodeKeyboard"] = "True"
        desired_caps["resetKeyboard"] = "True"


        self.driver = webdriver.Remote('http://192.168.10.156:4723/wd/hub', desired_caps)
        self.driver.implicitly_wait(1)

        #登录操作
        time.sleep(3)
        username=self.driver.find_element_by_id("com.jiudao.ccare:id/user_name")
        username.clear()
        username.send_keys("suser@umser")
        #assertThat(username.get_attribute("text"),equalTo("suser@umser"));  
        #校验
        #text=username.text
        self.assertEqual("suser@umser",username.get_attribute("text"),"username error")
        password=self.driver.find_element_by_id("com.jiudao.ccare:id/user_password")
        password.clear()
        password.send_keys("1")
        #self.assertEqual("杭州市",text2,"parent error")
        #勾选记住密码框
        self.driver.find_element_by_id("com.jiudao.ccare:id/keep_password").click()
        #勾选自动登录
        #self.driver.find_element_by_id("com.jiudao.ccare:id/auto_login").click()
        #进行登录
        self.driver.find_element_by_id("com.jiudao.ccare:id/login").click()
        time.sleep(4)

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

    #首页操作
    def homePage(self):
        """首页操作"""
        #左上角的首页控件
        e1=self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'首页')]").text
        self.assertEqual("首页",e1,"username error")
        #左下角的首页控件
        e2=self.driver.find_element_by_id("com.jiudao.ccare:id/main_activity_rb_one")
        e23=e2.text
        self.assertEqual("首页",e23,"username error")
        e2.click()
        time.sleep(1)

    #服务管理-等待处理事件数模块
    def wait(self):
        """服务管理-等待处理事件数模块"""
        time.sleep(1)
        self.driver.find_element_by_id("com.jiudao.ccare:id/main_activity_rb_two").click()
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'等待处理事件数')]").click()
        #进入第一个事件
        time.sleep(1)
        #self.driver.find_element_by_xpath("//android.widget.LinearLayout[contains(@index,0)]").click()
        self.driver.find_element_by_xpath("//android.widget.ListView/android.widget.LinearLayout[contains(@index,0)]").click()
        #资产信息
        time.sleep(0.5)
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'资产信息')]").click()
        #基本信息
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'基本信息')]").click()
        #历史信息
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'历史信息')]").click()
        #事件处理
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'事件处理')]").click()
        #状态弹出框
        self.driver.find_element_by_id("com.jiudao.ccare:id/fragment_event_deal_state").click()
        time.sleep(1)
        self.driver.find_element_by_xpath("//android.widget.CheckedTextView[contains(@text,'处理中')]").click()
        #输入反馈信息
        #self.driver.find_element_by_id("com.jiudao.ccare:id/fragment_event_deal_content").send_keys("你好")
        #self.driver.find_element_by_id("com.jiudao.ccare:id/fragment_event_deal_send").click()
        self.driver.find_element_by_xpath("//android.widget.ImageButton[contains(@content-desc,'转到上一层级')]").click()
        time.sleep(0.5)
        self.driver.find_element_by_xpath("//android.widget.ImageButton[contains(@content-desc,'转到上一层级')]").click()

    #服务管理-正在处理事件数模块
    def process(self):
        """服务管理-正在处理事件数模块"""
        time.sleep(1)
        self.driver.find_element_by_id("com.jiudao.ccare:id/main_activity_rb_two").click()
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'正在处理事件数')]").click()
        #进入第一个事件
        time.sleep(1)
        #self.driver.find_element_by_xpath("//android.widget.LinearLayout[contains(@index,0)]").click()
        self.driver.find_element_by_xpath("//android.widget.ListView/android.widget.LinearLayout[contains(@index,0)]").click()
        #资产信息
        time.sleep(3)
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'资产信息')]").click()
        #基本信息
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'基本信息')]").click()
        #历史信息
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'历史信息')]").click()
        #事件处理
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'事件处理')]").click()
        #状态弹出框
        self.driver.find_element_by_id("com.jiudao.ccare:id/fragment_event_deal_state").click()
        self.driver.find_element_by_xpath("//android.widget.CheckedTextView[contains(@text,'处理中')]").click()
        #输入反馈信息
        #self.driver.find_element_by_id("com.jiudao.ccare:id/fragment_event_deal_content").send_keys("")
        #self.driver.find_element_by_id("com.jiudao.ccare:id/fragment_event_deal_send").click()
        self.driver.find_element_by_xpath("//android.widget.ImageButton[contains(@content-desc,'转到上一层级')]").click()
        time.sleep(0.5)
        self.driver.find_element_by_xpath("//android.widget.ImageButton[contains(@content-desc,'转到上一层级')]").click()

    #服务管理-已完成事件数模块
    def completed(self):
        """服务管理-已完成事件数模块"""
        time.sleep(1)
        self.driver.find_element_by_id("com.jiudao.ccare:id/main_activity_rb_two").click()
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'已完成事件数')]").click()
        #进入第一个事件
        time.sleep(1)
        #self.driver.find_element_by_xpath("//android.widget.LinearLayout[contains(@index,0)]").click()
        self.driver.find_element_by_xpath("//android.widget.ListView/android.widget.LinearLayout[contains(@index,0)]").click()
        #资产信息
        time.sleep(0.5)
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'资产信息')]").click()
        #基本信息
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'基本信息')]").click()
        #历史信息
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'历史信息')]").click()
        #事件处理
        self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'事件处理')]").click()
        #状态弹出框
        self.driver.find_element_by_id("com.jiudao.ccare:id/fragment_event_deal_state").click()
        self.driver.find_element_by_xpath("//android.widget.CheckedTextView[contains(@text,'完成')]").click()
        #输入反馈信息
        #self.driver.find_element_by_id("com.jiudao.ccare:id/fragment_event_deal_content").send_keys("")
        #self.driver.find_element_by_id("com.jiudao.ccare:id/fragment_event_deal_send").click()
        self.driver.find_element_by_xpath("//android.widget.ImageButton[contains(@content-desc,'转到上一层级')]").click()
        time.sleep(0.5)
        self.driver.find_element_by_xpath("//android.widget.ImageButton[contains(@content-desc,'转到上一层级')]").click()

    #退出操作
    def exitAccount(self):
        """退出操作"""
        #进入关于蕴客界面
        time.sleep(2)
        e3=self.driver.find_element_by_id("com.jiudao.ccare:id/main_activity_rb_four")
        e3.click()
        #点击检查更新按钮
        update=self.driver.find_element_by_xpath("//android.widget.TextView[contains(@text,'检查更新')]")
        update.click()
        #点击退出按钮账号按钮
        exit=self.driver.find_element_by_id("com.jiudao.ccare:id/fragment_about_out_login")
        exit.click()


if __name__ == '__main__':
    suite = unittest.TestSuite()
    #suite.addTest(ContactsAndroidTests("login"))
    suite.addTest(ContactsAndroidTests("homePage"))
    suite.addTest(ContactsAndroidTests("wait"))
    suite.addTest(ContactsAndroidTests("process"))
    suite.addTest(ContactsAndroidTests("completed"))
    suite.addTest(ContactsAndroidTests("exitAccount"))
    timestr = time.strftime('%Y%m%d%H%M%S',time.localtime(time.time()))
    filename = "D:\\appium\\appiumresult\\result_" + timestr + ".html"
    print (filename)
    fp = open(filename, 'wb')
    runner = HTMLTestRunner.HTMLTestRunner(
                stream=fp,
                title='测试结果',
                description='测试报告'
                )
    #suite = unittest.TestLoader().loadTestsFromTestCase(ContactsAndroidTests)
    #unittest.TextTestRunner(verbosity=2).run(suite)
    runner.run(suite)
    #g_browser.quit()
    fp.close() #测试报告关闭


如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 11 条回复 时间 点赞
匿名 #1 · 2015年05月12日

可以把你的脚本结构调整一下

非 setup() 和 teardown() 方法,都放在一个自定义方法内,这样你最后也就可以只需要添加这一个方法到测试集里面就好了

#2 · 2015年05月12日 Author

#1 楼 @link1220 我也想过这样,但是代码一看一大片,结构性不行。如果脚本代码比较多,修复起来很头疼的

匿名 #3 · 2015年05月12日

#2 楼 @mads 其实个人觉得脚本如果都按照你这样写是肯定不行的。。。在快速迭代的开发模式下,版本、界面日新月异,如果业务逻辑稍作改动你岂不是要每个脚本挨个去修改。。。脚本少还好,达到一定规模,那是会弄死人的。。。
建议,可以考虑把你上面每一个自定义方法中的内容封装一下,脚本中只调封装后的方法,这样你的脚本正文中基本也就只要六句代码就够了,可读性、可维护性都会大大提升。

#4 · 2015年05月12日 Author

#3 楼 @link1220 _关键这么高大上的东西还不会写

大神,求解:
TypeError: unbound method addTest() must be called with TestSuite instance as first argument (got SimpleTest instance instead)

#6 · 2015年07月09日 Author

#5 楼 @samxupeiran 你贴个错,我怎么看。。

#6 楼 @mads 不好意思哈,目前已经解决了,非常感谢!

巧妙使用 unittest 机制,赞,遇到过类似的。

其实。unittest 还有两个类方法,叫 setUpClass 和 tearDownClass

#10 · 2015年07月10日 Author

#9 楼 @wang04170 ....别看这老帖子吐槽了,这个问题在我最新的帖子里很详细的写了解决方案了

回复

你好,麻烦能给一下这个您的关于这个解决方法帖子的链接吗?去你的主页没找到,谢谢

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