appium 学习笔记(七)

在测试报告里显示截图:

需要在测试报告中显示截图,首先需在运行脚本时进行截图

get_screenshot_as_file()是appium自带的截图方法

我们可以在每次进行断言前先进行截图(若在断言后截图,如果断言失败将不继续运行下面的代码)

from appium  import webdriver
import time
import adbbase
import unittest
import HTMLTestRunnerCN
import sys


class HappyFoodTest(unittest.TestCase): #自动化框架,继承unittest.TestCase
    """开心粮票"""

    @classmethod
    def setUpClass(cls): #准备测试环境,每个用例前执行
        desired_caps = {}
        desired_caps['platformName'] = 'Android'
        desired_caps['paltformVersion'] = adbbase.platformVersion()
        desired_caps['deviceName'] = adbbase.platformName()
        desired_caps['appPackage'] = adbbase.appPackage()
        desired_caps['appActivity'] = adbbase.appActivity()
        global driver
        driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps)

        time.sleep(5)

    def test_login(self): #用例,以test开头;登录测试
        """登录"""
        driver.find_element_by_id("phoneNumber").send_keys("13575220850")
        driver.find_element_by_id("passWord").send_keys("q0125016")
        driver.back()
        driver.find_element_by_id("login").click()
        time.sleep(1)
        try:  #自动点击app授权弹框
            button = driver.find_element_by_xpath("//android.widget.Button[contains(@text,'允许')]")
            button.click()
        except:
            print("自动点击应用app授权出错!")
        time.sleep(1)
        driver.get_screenshot_as_file("./scr/"+sys._getframe().f_code.co_name+'.png')
        title = driver.find_element_by_id("com.happy.food:id/title").text
        self.assertEqual(title,"开心粮票")

    def test_billing_details(self):
        """结算详情"""
        driver.find_element_by_id("com.happy.food:id/mine").click()
        driver.find_element_by_id("com.happy.food:id/balanceDetail").click()
        driver.get_screenshot_as_file("./scr/"+sys._getframe().f_code.co_name+'.png')
        title = driver.find_element_by_id("com.happy.food:id/title").text
        self.assertEqual(title,"结算详情")

    @classmethod
    def tearDownClass(cls): #清理环境,用例执行完后执行
        driver.quit()

def Suite():
    suiteTest = unittest.TestSuite()
    suiteTest.addTest(HappyFoodTest("test_login"))
    suiteTest.addTest(HappyFoodTest("test_billing_details"))
    return suiteTest

if __name__ == '__main__':
    now = time.strftime("%Y-%m-%d--%H;%M", time.localtime())
    filepath = './report/'+ now + '.html'
    fp = open(filepath,'wb')
    runner = HTMLTestRunnerCN.HTMLTestRunner(
        stream=fp,
        title='自动化报告',
        tester='lin'
    )
    runner.run(Suite())
    fp.close()

sys._getframe().f_code.co_name为获取当前函数名,使用前需前导入sys方法 import sys

这里获取的结局将以当前函数名保存在 ./scr/ 文件夹内。如 ./scr/test_login.png


有了截图后我们需要在报告中导入截图,需要修改HTMLTestRunnerCN.py文件

先增加“截图”一列

搜索"text-center success" 找到以下代码

<tr id='header_row' class="text-center success" style="font-weight: bold;font-size: 14px;">
    <td>用例集/测试用例</td>
    <td>总计</td>
    <td>通过</td>
    <td>失败</td>
    <td>错误</td>
    <td>详细</td>
</tr>

增加<td>截图</td>

<tr id='header_row' class="text-center success" style="font-weight: bold;font-size: 14px;">
    <td>用例集/测试用例</td>
    <td>总计</td>
    <td>通过</td>
    <td>失败</td>
    <td>错误</td>
    <td>详细</td>
    <td>截图</td>
</tr>

修改后生产的报告是这样的

appium 学习笔记(七)

在Case大类和总计行下我们还需要添加对应的列

继续修改HTMLTestRunnerCN.py文件

搜索"%(style)s warning"

找到以下代码

<tr class='%(style)s warning'>
    <td>%(desc)s</td>
    <td class="text-center">%(count)s</td>
    <td class="text-center">%(Pass)s</td>
    <td class="text-center">%(fail)s</td>
    <td class="text-center">%(error)s</td>
    <td class="text-center"><a href="javascript:showClassDetail('%(cid)s',%(count)s)" class="detail" id='%(cid)s'>详细</a></td>
</tr>

在后面添加一个空列表<td>&nbsp;</td>

<tr class='%(style)s warning'>
    <td>%(desc)s</td>
    <td class="text-center">%(count)s</td>
    <td class="text-center">%(Pass)s</td>
    <td class="text-center">%(fail)s</td>
    <td class="text-center">%(error)s</td>
    <td class="text-center"><a href="javascript:showClassDetail('%(cid)s',%(count)s)" class="detail" id='%(cid)s'>详细</a></td>
    <td>&nbsp;</td>
</tr>

搜索"text-center active"

找到以下代码

<tr id='total_row' class="text-center active">
    <td>总计</td>
    <td>%(count)s</td>
    <td>%(Pass)s</td>
    <td>%(fail)s</td>
    <td>%(error)s</td>
    <td>通过率:%(passrate)s</td>
</tr>

同样添加一个空列表

<tr id='total_row' class="text-center active">
    <td>总计</td>
    <td>%(count)s</td>
    <td>%(Pass)s</td>
    <td>%(fail)s</td>
    <td>%(error)s</td>
    <td>通过率:%(passrate)s</td>
    <td>&nbsp;</td>
</tr>

现在的报告是这样

appium 学习笔记(七)

现在定义截图的路径

搜索倒到函数_generate_report_test(self, rows, cid, tid, n, t, o, e)

def _generate_report_test(self, rows, cid, tid, n, t, o, e):
    # e.g. 'pt1.1', 'ft1.1', etc
    has_output = bool(o or e)
    # ID修改点为下划线,支持Bootstrap折叠展开特效 - Findyou
    tid = (n == 0 and 'p' or 'f') + 't%s_%s' % (cid+1,tid+1)
    name = t.id().split('.')[-1]
    doc = t.shortDescription() or ""
    desc = doc and ('%s: %s' % (name, doc)) or name
    tmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL

    # utf-8 支持中文 - Findyou
     # o and e should be byte string because they are collected from stdout and stderr?
    if isinstance(o, str):
        # TODO: some problem with 'string_escape': it escape \n and mess up formating
        # uo = unicode(o.encode('string_escape'))
        # uo = o.decode('latin-1')
        uo = o
    else:
        uo = o
    if isinstance(e, str):
        # TODO: some problem with 'string_escape': it escape \n and mess up formating
        # ue = unicode(e.encode('string_escape'))
        # ue = e.decode('latin-1')
        ue = e
    else:
        ue = e

    script = self.REPORT_TEST_OUTPUT_TMPL % dict(
        id = tid,
        output = saxutils.escape(uo+ue),
    )

    row = tmpl % dict(
        tid = tid,
        Class = (n == 0 and 'hiddenRow' or 'none'),
        style = n == 2 and 'errorCase' or (n == 1 and 'failCase' or 'passCase'),
        desc = desc,
        script = script,
        status = self.STATUS[n],
    )
    rows.append(row)
    if not has_output:
        return

在row = tmpl % dict()里添加截图的路径

row = tmpl % dict(
    tid = tid,
    Class = (n == 0 and 'hiddenRow' or 'none'),
    style = n == 2 and 'errorCase' or (n == 1 and 'failCase' or 'passCase'),
    desc = desc,
    script = script,
    status = self.STATUS[n],
    screenshot = "../scr/"+name+".png"
)


最后搜索"%(Class)s" 到到以下代码

<tr id='%(tid)s' class='%(Class)s'>
    <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
    <td colspan='5' align='center'>
    <!--默认收起错误信息 -Findyou
    <button id='btn_%(tid)s' type="button"  class="btn btn-danger btn-xs collapsed" data-toggle="collapse" data-target='#div_%(tid)s'>%(status)s</button>
    <div id='div_%(tid)s' class="collapse">  -->
    <!-- 默认展开错误信息 -Findyou -->
    <button id='btn_%(tid)s' type="button"  class="btn btn-danger btn-xs" data-toggle="collapse" data-target='#div_%(tid)s'>%(status)s</button>
    <div id='div_%(tid)s' class="collapse in">
    <pre>
    %(script)s
    </pre>
    </div>
    </td>
</tr>

添加图片

<tr id='%(tid)s' class='%(Class)s'>
    <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
    <td colspan='5' align='center'>
    <!--默认收起错误信息 -Findyou
    <button id='btn_%(tid)s' type="button"  class="btn btn-danger btn-xs collapsed" data-toggle="collapse" data-target='#div_%(tid)s'>%(status)s</button>
    <div id='div_%(tid)s' class="collapse">  -->
    <!-- 默认展开错误信息 -Findyou -->
    <button id='btn_%(tid)s' type="button"  class="btn btn-danger btn-xs" data-toggle="collapse" data-target='#div_%(tid)s'>%(status)s</button>
    <div id='div_%(tid)s' class="collapse in">
    <pre>
    %(script)s
    </pre>
    </div>
    </td>
    <td class="image" align='center'>
    <img src="%(screenshot)s" alt="pic" width="288" height="512">
    </td>
</tr>


现在我们生成的报告就会自带截图了

appium 学习笔记(七)