zoukankan      html  css  js  c++  java
  • Web自动化测试05

    本篇博客

    unittest模块

    1 unittest基本概念
    2 unittest基本用法
    3 unittest断言
    4 unittest命令行接口
    5 unittest与selenium

    unittest模块

    1 unittest基本概念

    1) 什么是是unittest框架?

    Unittest单元测试框架是专门用来进行测试的框架

    2) 主要概念:

    test fixture: 代表了用例执行前的准备工作和用例执行之后的清理工作。

    test fixture

    test case: 测试用例,这个相信大家都不陌生。是测试的最小单位,一般检查一组输入的响应(输出)是否符合预期。unittest模块提供了TestCase类来帮助我们创建测试用例;

    test case

    test suite: 经常被翻译成”测试套件”,也有人称为”测试套”,是测试用例或测试套件的集合,一般用来把需要一起执行的用例组合到一起;

    test suite

    test runner: 用来执行测试用例并输出测试结果的组件。可以是图形界面或命令行界面;

    test runner

    2 unittest基本用法 

    unittest基本用法:

    1.通过继承unittest.TestCase进行编写,继承unittest.TestCase的类会被框架识别为测试用例。

    2.setUp和TearDown是用于事前和事后做相关处理动作的,就是前面说的Test Fixture,会在每个测试用例运行前后被框架自动调用

    3.所有以test开头的方法会被框架自动识别为测试用例,并自动调用执行,不是以test开头的不会被调用

    4.unittest.main()是最简单的测试执行方式

    5.调用unittest.main()方法后,继承自unittest.TestCase类的类会被自动识别为测试用例并且被调用。

    6.test suite: 经常被翻译成”测试套件”,(另一种测试调用方法)也有人称为”测试套”,是测试用例或测试套件的集合,一般用来把需要一起执行的用例组合到一起;

    案例1:简单测试

    1.unittest.main()运行时,框架自动寻找TestCase子类,并且运行
    2.在TestCase类中,只把以test开头的方法当做测试用例,然后执行,是有顺序的,字母或者数字。

    # 导入unittest模块
    import unittest
    
    # 继承TestCase类,TestCase类是测试用例类
    class Test1(unittest.TestCase):
    
        def test_001(self):
            print('001')
    
        def test_003(self):
            print('003')
    
        def test_002(self):
            print('002')
    
    
    if __name__ == '__main__':
        unittest.main()

    案例2:Test1,Test2都会被调用。因为都继承了TestCase

    # 导入unittest模块
    import unittest
    
    # 继承TestCase类,TestCase类是测试用例类
    class Test1(unittest.TestCase):
    
    
        def test_001(self):
            print('001')
    
        def test_002(self):
            print('002')
    
        def test_003(self):
            print('003')
    
    class Test2(unittest.TestCase):
    
        def test_001(self):
            print('201')
    
        def test_002(self):
            print('202')
    
    if __name__ == '__main__':
        unittest.main()

    案例3:

    1 setUp()用于初始化一些参数,在测试用例执行前自动被调用

    2 tearDown()用于清理,在测试用例执行后被调用

    # 导入unittest模块
    import unittest
    
    # 继承TestCase类,TestCase类是测试用例类
    class Test1(unittest.TestCase):
        def setUp(self):
            print('hello')
    
        def tearDown(self):
            print('bye')
    
        def test_001(self):
            print('001')
    
        def test_002(self):
            print('002')
    
        def test_003(self):
            print('003')
    
    
    
    if __name__ == '__main__':
        unittest.main()
    
    
    
    # 1.unittest.main()运行时,框架自动寻找TestCase子类,并且运行
    # 2.在TestCase类中,只把以test开头的方法当做测试用例,然后执行
    # 3.setUp()用于初始化一些参数,在测试用例执行前自动被调用,tearDown()用于清理,在测试用例执行后被调用
    # 4.setUp,tearDown。每个用例开始和结束调用相应的代码。

    test suite: 经常被翻译成”测试套件”,也有人称为”测试套”,是测试用例或测试套件的集合,一般用来把需要一起执行的用例组合到一起;

    下面是测试套件的用法:

    1.创建测试套件

    suit = unittest.TestSuite()

    2. 定义一个测试用例列表,逐个添加

    case_list= ['test_001','test_002','test_003']
        for case in case_list:
            suit.addTest(Test1(case))

    3.运行测试用例,verbosity=2(固定)为每一个测试用例输出报告,run的参数是测试套件

    unittest.TextTestRunner(verbosity=2).run(suit)

    案例4:测试套件

    # 导入unittest模块
    import unittest
    
    # 继承TestCase类,TestCase类是测试用例类
    class Test1(unittest.TestCase):
        def setUp(self):
            print('hello')
    
        def tearDown(self):
            print('bye')
    
        def test_001(self):
            print('001')
    
        def test_002(self):
            print('002')
    
        def test_003(self):
            print('003')
    
    
    
    if __name__ == '__main__':
        # 第一种调用:
        # unittest.main()
    
        # 第二种调用
        # 创建测试套件
        suit = unittest.TestSuite()
        # 定义一个测试用例列表
        case_list= ['test_001','test_002','test_003']
        for case in case_list:
            suit.addTest(Test1(case))
    
        # 运行测试用例,verbosity=2为每一个测试用例输出报告,run的参数是测试套件
        unittest.TextTestRunner(verbosity=2).run(suit)

    3 unittest断言

    unittest断言:

    断言是测试用例的核心。我们使用assertEqual()来判断预期结果,用assertTrue()和assertFalse来做是非判断。

    案例:断言测试

    import unittest
    
    class Test(unittest.TestCase):
        def setUp(self):
            print('start')
    
        def tearDown(self):
            print('bye')
    
        def test_001(self):
            self.assertEqual('1','1')
    
        def test_002(self):
            self.assertEqual('1','0')
    
    if __name__ == '__main__':
        unittest.main()

    跑了2个测试用例,一个通过,一个失败。期待为1,结果为0。

    显示代码错误的地方:

     

    4 unittest命令行接口

    unittest命令行接口:

    unittest支持命令行接口,我们可以在命令行里指定运行具体的测试用例。

    python -m unittest test.Tese1

    5 unittest与selenium

    unittest与selenium

    前面我们简单学习了unittest的用法,接下来我们将unittest与selenium融合在一起进行web自动化测试

    目录结构:

    1. Commonlib目录存放通用模块(我们封装的selenium模块)

    2. 创建Business目录 ,根据业务创建测试功能模块

    3. 创建Testcase目录存放测试用例

    1. Commonlib-Commonlib.py(后面会用到)

    from selenium import webdriver
    import time
    
    class Commonshare(object):
        # 初始化方法
        def __init__(self):
            # 创建浏览器对象
            self.driver = webdriver.Firefox()
            # 设置隐式等待
            self.driver.implicitly_wait(5)
            # 设置浏览器的最大化
            self.driver.maximize_window()
    
        def open_url(self,url):
            # 请求指定站点
            self.driver.get(url)
            time.sleep(3)
    
        def locateElement(self, locate_type, value):
            # 判断定位方式并调用相关方法
            el = None
            if locate_type == 'id':
                el = self.driver.find_element_by_id(value)
            elif locate_type == 'name':
                el = self.driver.find_element_by_name(value)
            elif locate_type == 'class':
                el = self.driver.find_element_by_class_name(value)
            elif locate_type == 'text':
                el = self.driver.find_element_by_link_text(value)
            elif locate_type == 'xpath':
                el = self.driver.find_element_by_xpath(value)
            elif locate_type == 'css':
                el = self.driver.find_element_by_css_selector(value)
            # 如果el不为None,则返回
            if el is not None:
                return el
    
        # 指定对某一元素的点击操作
        def click(self, locate_type, value):
            # 调用定位方法进行元素定位
            el = self.locateElement(locate_type,value)
            # 执行点击操作
            el.click()
            time.sleep(1)
    
        # 对指定的元素进行数据输入
        def input_data(self,locate_type,value,data):
            # 调用定位方法进行元素定位
            el = self.locateElement(locate_type,value)
            # 执行输入操作
            el.send_keys(data)
    
        # 获取指定元素的文本内容
        def get_text(self, locate_type, value):
            # 调用定位方法进行元素定位
            el = self.locateElement(locate_type, value)
            return el.text
    
        # 获取指定元素的属性值
        def get_attr(self, locate_type, value, data):
            # 调用定位方法进行元素定位
            el = self.locateElement(locate_type, value)
            return el.get_attribute(data)
    
    
    
        # 收尾清理方法
        def __del__(self):
            time.sleep(3)
            self.driver.quit()
    
    if __name__ == '__main__':
        pass

    2. Business-Login.py(后面会用到)

     下面加了time.sleep()。因为后面案例2,3个测试用例,有2个都报错说没有定位到元素。因为网络太慢了,所以就加了延迟时间就可以了。

    # 导入selenium封装类
    import sys
    sys.path.append("..")
    from Commonlib.Commonlib import Commonshare
    import time
    
    
    class Login(Commonshare):
        def login(self,user,pwd):
            self.open_url('http://www.yhd.com/')
            self.click('class','hd_login_link')
            time.sleep(2)
            self.input_data('id','un',user)
            time.sleep(2)
            self.input_data('id','pwd',pwd)
            time.sleep(2)
            self.click('id','login_button')
    
    if __name__ == '__main__':
        log = Login()
        log.login('hack_ai_buster','1qaz2wsx#EDC')

    案例1:登陆1号店,简单调用。

    Testcase-testcase.py

    import sys
    sys.path.append("..")
    from Business.Login import Login
    import unittest
    
    
    class Test(unittest.TestCase):
        def setUp(self):
            print('hello')
    
        def tearDown(self):
            print('bye')
    
        # 定义正确登陆的测试用例
        # def test_001(self):
        #     log = Login()
        #     # 用账号密码登录
        #     log.login('18001225175','zyc123')
        #     # 获取登录之后的用户名
        #     data = log.get_text('class','hd_login_name')
        #     # 断言,判断登录后的用户名是否和预期用户名相同
        #     self.assertEqual('1800*****75@phone',data)
    
        # 账号密码都不输入,直接登录
        def test_002(self):
            log = Login()
            # 用账号密码登录
            log.login('', '')
            # 获取登录之后的用户名
            data = log.get_text('id','error_tips')
            # 断言,判断登录后的用户名是否和预期用户名相同
            self.assertEqual('请输入账号和密码',data)
    
        # 只输入账号不输入密码,直接登录
        def test_003(self):
            log = Login()
            # 用账号密码登录
            log.login('sdfsdadfa', '')
            # 获取登录之后的用户名
            data = log.get_text('id', 'error_tips')
            # 断言,判断登录后的用户名是否和预期用户名相同
            self.assertEqual('请输入密码', data)
    
        # 只输入账号不输入密码,直接登录
        def test_004(self):
            log = Login()
            # 用账号密码登录
            log.login('sdfsdadfa', '')
            # 获取登录之后的用户名
            data = log.get_text('id', 'error_tips')
            # 断言,判断登录后的用户名是否和预期用户名相同
            self.assertEqual('请输入密码itcast', data)
    
    if __name__ == '__main__':
        unittest.main()

     注意:为了让后面的案例能够轻松的完成测试。test_001(正确的账号和密码)我注销了,后面的案例都不用这个,因为正确的账号密码输入,会有动态的拖图验证。有的时候弄不好,结果就不对。而且,不在空白处点,会只运行案例一,然后会报一个找不到句柄的错。为了引起不要的麻烦,运行后面三个案例就行。

    如果想要运行test_001的代码,(正确的账号和密码)可以加time时间延长:

      # 定义正确登陆的测试用例
        def test_001(self):
            log = Login()
            # 用账号密码登录
            time.sleep(2)
            log.login('18001225175','zyc123')
    
            # 获取登录之后的用户名
            time.sleep(10)
            data = log.get_text('class','hd_login_name')
    
            # 断言,判断登录后的用户名是否和预期用户名相同
            time.sleep(2)
            self.assertEqual('1800*****75@phone',data)

    结果是:一个测试用例失败,三个测试用例通过。这是对的。

    案例2:登陆1号店,测试套件调用。

    Testcase-testsuit.py

    import unittest
    import sys
    sys.path.append("..")
    from Testcase.testcase import Test
    # 导入HtmlTextRunner,用于生成html的测试报告
    from Commonlib.HTMLTestRunner import HTMLTestRunner
    
    class SuitTest(unittest.TestCase):
        def test_suit(self):
            case_list = ['test_002','test_003','test_004']
            # 创建测试套件
            mysuit = unittest.TestSuite()
    
            # 循环将测试用例放到测试套件中
            for case in case_list:
                mysuit.addTest(Test(case))
    
            # 创建测试运行器,设置为每一个测试用例生成测试报告,运行测试套件中的测试用例
            unittest.TextTestRunner(verbosity=2).run(mysuit)
    
    
    
    if __name__ == '__main__':
        unittest.main()

    下面为什么总的是4个?因为Testcase-testsuit.py本身也算一个测试用例,所以是4个。

    下面为什么只有3个测试用例结果?因为unittest.TextTestRunner(verbosity=2).run(mysuit)运行的是mysuit,所以具体的就mysiut定义的3个。

     

    案例3:登陆1号店。

    Testcase-testsuit2.py

    import unittest
    import sys
    sys.path.append("..")
    from Testcase.testcase import Test
    # 导入HtmlTextRunner,用于生成html的测试报告
    from Commonlib.HTMLTestRunner import HTMLTestRunner
    
    class SuitTest(unittest.TestCase):
        def test_suit(self):
            case_list = ['test_002','test_003','test_004']
            # 创建测试套件
            mysuit = unittest.TestSuite()
    
            # 循环将测试用例放到测试套件中
            for case in case_list:
                mysuit.addTest(Test(case))
    
            # 创建测试运行器,设置为每一个测试用例生成测试报告,运行测试套件中的测试用例
            # unittest.TextTestRunner(verbosity=2).run(mysuit)
    
            # 生成html测试报告
            with open('report.html','wb')as f:
                HTMLTestRunner(
                    stream=f,           # 相当于f.write(报告)
                    title='第一个测试报告',
                    description='it黑马第一个测试报告',
                    verbosity=2         # 为每个测试用例生成测试报告
                ).run(mysuit)
    
    
    if __name__ == '__main__':
        unittest.main()

     

    生成report.html测试报告。可以在目录双击打开,也可以在pycharm中点击右上的浏览器图标。

    可以看到下面有3个测试用例,一个失败,两个通过。

    可以看到失败的一个测试用例具体错误的地方:

    期待:请输入密码itcast      结果:请输入密码    ( 因为是不符的,所以失败。)

     

    附:Commonlib-HTMLTestRunner.py(有点长哦)

    https://www.cnblogs.com/zhangyangcheng/diary/2020/03/19/12523394.html

     

  • 相关阅读:
    [07] Redis 持久化
    [06] Redis 事务
    [05] Jedis
    [04] Redis 配置文件
    [03] Redis 数据类型
    [02] Redis 简介&安装
    [01] NoSQL 简介
    06-NULL&typedef
    05-动态内存分配
    朴素贝叶斯分类器Naive Bayes
  • 原文地址:https://www.cnblogs.com/zhangyangcheng/p/12520218.html
Copyright © 2011-2022 走看看