<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      xcq-bj

      導(dǎo)航

       

      DAY-09課堂筆記


      UnitTest基本使用

      UnitTest框架介紹

      • 框架

        什么是框架?
        1. 框架英文單詞framework
        2. 為解決一類事情的功能集合
        
      • UnitTest框架

        是Python自帶的一個(gè)單元測(cè)試框架
        - ?帶的, 可以直接使?, 不需要單外安裝
        - 測(cè)試?員 ?來(lái)做?動(dòng)化測(cè)試, 作為?動(dòng)化測(cè)試的執(zhí)?框架, 即 管理和執(zhí)??例的
        
      • 為什么使用UnitTest框架?

        1. 能夠組織多個(gè)用例去執(zhí)行
        2. 提供豐富的斷言方法
        3. 能夠生成測(cè)試報(bào)告
        
      • UnitTest 核心要素(組成)

        1. TestCase 測(cè)試?例, 這個(gè)測(cè)試?例是 unittest 的組成部分,作?是 ?來(lái)書(shū)寫真正的?例代碼(腳本)
        
        2. Testsuite 測(cè)試套件, 作?是?來(lái)組裝(打包)TestCase(測(cè)試?例) 的,即 可以將多個(gè)?例腳本?件 組裝到?起
        
        3. TestRunner 測(cè)試執(zhí)?(測(cè)試運(yùn)?), 作? 是?例執(zhí)?TestSuite(測(cè)試套件)的
        
        4. TestLoader 測(cè)試加載, 是對(duì) TestSuite(測(cè)試套件) 功能的補(bǔ)充, 作?是?來(lái)組裝(打包) TestCase(測(cè)試?例) 的
        
        5. Fixture 測(cè)試夾具, 是?種代碼結(jié)構(gòu), 書(shū)寫 前置?法(執(zhí)??例之前的?法)代碼 和后置?法(執(zhí)??例之后的?法) 代碼 ,即 ?例執(zhí)?順序 前置 ---> ?例 ---> 后置
        

      書(shū)寫真正的?例代碼(腳本) 單獨(dú)?個(gè)測(cè)試?例 也是可以執(zhí)?
      • 步驟:

        1. 導(dǎo)包 unittest
        2. 定義測(cè)試類, 需要繼承 unittest.TestCase 類, 習(xí)慣性類名以 Test 開(kāi)頭
        3. 書(shū)寫測(cè)試?法, 必須以 test 開(kāi)頭
        4. 執(zhí)?
        
      • 注意事項(xiàng)

        1. 代碼?件名字 要滿?標(biāo)識(shí)符的規(guī)則
        2. 代碼?件名 不要使?中?
        
      • 代碼

        # 1. 導(dǎo)包
        import unittest
        
        
        # 2. 定義測(cè)試類:新建 測(cè)試類 ;只要繼承unittest.TestCase類,就是測(cè)試類
        class TestDemo(unittest.TestCase):
        
            # 3. 定義測(cè)試方法:測(cè)試方法名稱命名必須以test開(kāi)頭
            def test_01(self):
                print("測(cè)試一")
        
            def test_02(self):
                print("測(cè)試二")
        
        # 4.執(zhí)行
        # 4.1 在類名或者?法名后邊右鍵運(yùn)?
        # 4.1.1 在類名后邊, 執(zhí)?類中的所有的測(cè)試?法
        # 4.1.2 在?法名后邊, 只執(zhí)?當(dāng)前的測(cè)試?法
        
        

      TestSuite 測(cè)試套件 和 TextTestRunner 測(cè)試執(zhí)?

      TestSuite(測(cè)試套件)

      將多條?例腳本集合在?起,就是套件, 即?來(lái)組裝?例的
      
      • 步驟

        1. 導(dǎo)包 unittest
        2. 實(shí)例化套件對(duì)象 unittest.TestSuite()
        3. 添加?例?法
        

      TextTestRunner 測(cè)試執(zhí)?

      ?來(lái)執(zhí)?套件對(duì)象
      
      • 步驟

        1. 導(dǎo)包 unittest
        2. 實(shí)例化 執(zhí)?對(duì)象 unittest.TextTestRunner()
        3. 執(zhí)?對(duì)象執(zhí)? 套件對(duì)象 執(zhí)?對(duì)象.run(套件對(duì)象)
        

      整體步驟

      1. 導(dǎo)包 unittest
      2. 實(shí)例化套件對(duì)象 unittest.TestSuite()
      3. 添加?例?法
      -  3.1 套件對(duì)象.addTest(測(cè)試類名('測(cè)試?法名'))
      4. 實(shí)例化 執(zhí)?對(duì)象 unittest.TextTestRunner()
      5. 執(zhí)?對(duì)象執(zhí)? 套件對(duì)象 執(zhí)?對(duì)象.run(套件對(duì)象)
      
      # 1. 導(dǎo)包 unittest
      import unittest
      from TestCase import TestDemo
      from TestCase_01 import TestDemo01
      
      # 2. 實(shí)例化套件對(duì)象 unittest.TestSuite()
      suite = unittest.TestSuite()
      # 3. 添加?例?法
      # -  3.1 套件對(duì)象.addTest(測(cè)試類名('測(cè)試?法名'))
      suite.addTest(TestDemo('test_01'))
      suite.addTest(TestDemo('test_02'))
      suite.addTest(TestDemo01('test_03'))
      suite.addTest(TestDemo01('test_04'))
      
      # -  3.2套件對(duì)象.addTest(unittest.makeSuite(測(cè)試類名)) # 在
      不同的 Python 版本中,可能沒(méi)有提示
      suite.addTest(unittest.makeSuite(TestDemo1))
      suite.addTest(unittest.makeSuite(TestDemo2))
      
      #  - 3.3
      suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestDemo1))
      suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestDemo2))
      
      # 4. 實(shí)例化 執(zhí)?對(duì)象 unittest.TextTestRunner()
      
      runner = unittest.TextTestRunner()
      # 5. 執(zhí)?對(duì)象執(zhí)? 套件對(duì)象 執(zhí)?對(duì)象.run(套件對(duì)象)
      runner.run(suite)
      

      TestLoader 測(cè)試加載

      作?和 TestSuite 作??樣,組裝?例代碼, 同樣也需要使?TextTestRunner() 去執(zhí)?
      
      需要使用10 個(gè)?例腳本 makeSuite()
      
      使用unittest.TestLoader,通過(guò)該類下面的discover()方法自動(dòng)搜索指定目錄下指定開(kāi)頭的.py文件,并將查找到的測(cè)試用例組裝到測(cè)試套件。
      

      步驟

      1. 導(dǎo)包 unittest
      2. 實(shí)例化加載對(duì)象并加載?例 ---> 得到的是 套件對(duì)象(最終返回的還是測(cè)試套件對(duì)象,運(yùn)行測(cè)試套件還需要使用TestRunner)
      3. 實(shí)例化執(zhí)?對(duì)象并執(zhí)?
      
      import unittest
      
      # 實(shí)例化加載對(duì)象并加載?例,得到套件對(duì)象
      # suite = unittest.TestLoader().discover('?例所在的?錄', '?例代碼?件名*.py')
      suite = unittest.TestLoader().discover("./", "hm_02*.py")
      
      # runner=unittest.TextTestRunner()
      # runner.run(suite)
      
      unittest.TextTestRunner().run(suite)
      

      練習(xí)

      1.

      1. 創(chuàng)建?個(gè)?錄 case, 作?就是?來(lái)存放?例腳本,
      2. 在這個(gè)?錄中創(chuàng)建 5 個(gè)?例代碼?件 , test_case1.py
      ...
      3. 使? TestLoader 去執(zhí)??例
      -----
      將來(lái)的代碼 ?例都是單獨(dú)的?錄 中存放的
      test_項(xiàng)?_模塊_功能.py
      
      import unittest
      
      suite = unittest.TestLoader().discover('case', 'test_case*.py')
      
      unittest.TextTestRunner().run(suite)
      

      2.

      1. 定義?個(gè) tools 模塊, 在這個(gè)模塊中 定義 add 的?法,可
      以對(duì)兩個(gè)數(shù)字求和,返回求和結(jié)果
      2. 書(shū)寫?例, 對(duì) add() 函數(shù)進(jìn)?測(cè)試
      1, 1, 2
      1, 2, 3
      3, 4, 7
      4, 5, 9
      -----
      之前的測(cè)試?法,直接?個(gè) print
      這個(gè)案例中的 測(cè)試?法,調(diào)? add 函數(shù), 使? if 判斷,來(lái)判斷
      預(yù)期結(jié)果和實(shí)際結(jié)果是否相符
      預(yù)期結(jié)果 2 3 7 9
      實(shí)際結(jié)果 調(diào)? add()
      
      import unittest
      from tools import add
      
      class testadd(unittest.TestCase):
          def test1(self):
              """1,1,2"""
              print(f"測(cè)試數(shù)據(jù)為:{1},{1},{2}")
              if 2==add(1,1):
                  print(f"測(cè)試數(shù)據(jù)為:{1},{1},{2}通過(guò)")
              else:
                  print(f"測(cè)試數(shù)據(jù)為:{1},{1},{2}不通過(guò)")
      
      
          def test2(self):
              """1,2,3"""
              print(f"測(cè)試數(shù)據(jù)為:{1},{2},{3}")
              if 3==add(1,2):
                  print(f"測(cè)試數(shù)據(jù)為:{1},{2},{3}通過(guò)")
              else:
                  print(f"測(cè)試數(shù)據(jù)為:{1},{2},{3}不通過(guò)")
      
      
          def test3(self):
              """3,4,7"""
              print(f"測(cè)試數(shù)據(jù)為:{3},{4},{7}")
              if 3==add(1,2):
                  print(f"測(cè)試數(shù)據(jù)為:{3},{4},{7}通過(guò)")
              else:
                  print(f"測(cè)試數(shù)據(jù)為:{3},{4},{7}不通過(guò)")
      
          def test4(self):
              """4,5,9"""
              print(f"測(cè)試數(shù)據(jù)為:{4},{5},{9}")
              if 3==add(1,2):
                  print(f"測(cè)試數(shù)據(jù)為:{4},{5},{9}通過(guò)")
              else:
                  print(f"測(cè)試數(shù)據(jù)為:{4},{5},{9}不通過(guò)")
      

      Fixture

      代碼結(jié)構(gòu), 在?例執(zhí)?前后會(huì)?動(dòng)執(zhí)?的代碼結(jié)構(gòu)
      tpshop 登錄
      1. 打開(kāi)瀏覽器 (?次)
      2. 打開(kāi)??,點(diǎn)擊登錄 (每次)
      3. 輸??戶名密碼驗(yàn)證碼1,點(diǎn)擊登錄 (每次, 測(cè)試?法)
      4. 關(guān)閉?? (每次)
      2. 打開(kāi)??,點(diǎn)擊登錄 (每次)
      3. 輸??戶名密碼驗(yàn)證碼2,點(diǎn)擊登錄 (每次, 測(cè)試?法)
      4. 關(guān)閉?? (每次)
      2. 打開(kāi)??,點(diǎn)擊登錄 (每次)
      3. 輸??戶名密碼驗(yàn)證碼3,點(diǎn)擊登錄 (每次, 測(cè)試?法)
      4. 關(guān)閉?? (每次)
      5. 關(guān)閉瀏覽器 (?次)
      

      方法級(jí)別Fixture

      在每個(gè)?例執(zhí)?前后都會(huì)?動(dòng)調(diào)?, ?法名是固定的
      
      def setUp(self): # 前置
       # 每個(gè)?例執(zhí)?之前都會(huì)?動(dòng)調(diào)?
       pass
      
      
      def tearDown(self): # 后置
       # 每個(gè)?例執(zhí)?之后 都會(huì)?動(dòng)調(diào)?
       pass
      # ?法前置 ?例 ?法后置
      # ?法前置 ?例 ?法后置
      

      類級(jí)別Fixture

      在類中所有的測(cè)試?法執(zhí)?前后 會(huì)?動(dòng)執(zhí)?的代碼, 只執(zhí)??次
      
      # 類級(jí)別的 Fixture 需要寫作類?法
      @classmethod
      def setUpClass(cls): # 類前置
       	pass
      
      
      @classmethod
      def tearDownClass(cls): # 后置
       	pass
      # 類前置 ?法前置 ?例 ?法后置 ?法前置 ?例 ?法后置類后置
      

      模塊級(jí)別Fixture(了解)

      模塊, 就是代碼?件
      模塊級(jí)別 在這個(gè)代碼?件執(zhí)?前后執(zhí)??次
      
      # 在類外部定義函數(shù)
      def setUpModule():
           pass
          
          
      def tearDownModule():
           pass
      
      實(shí)現(xiàn):
      tpshop 登錄
      1. 打開(kāi)瀏覽器 (?次)
      2. 打開(kāi)??,點(diǎn)擊登錄 (每次)
      3. 輸??戶名密碼驗(yàn)證碼1,點(diǎn)擊登錄 (每次, 測(cè)試?法)
      4. 關(guān)閉?? (每次)
      2. 打開(kāi)??,點(diǎn)擊登錄 (每次)
      3. 輸??戶名密碼驗(yàn)證碼2,點(diǎn)擊登錄 (每次, 測(cè)試?法)
      4. 關(guān)閉?? (每次)
      2. 打開(kāi)??,點(diǎn)擊登錄 (每次)
      3. 輸??戶名密碼驗(yàn)證碼3,點(diǎn)擊登錄 (每次, 測(cè)試?法)
      4. 關(guān)閉?? (每次)
      5. 關(guān)閉瀏覽器 (?次)
      
      import unittest
      
      
      class TestLogin(unittest.TestCase):
      
          @classmethod
          def setUpClass(cls) -> None:
              print("1.打開(kāi)瀏覽器")
      
          def setUp(self) -> None:
              print("2.打開(kāi)??, 點(diǎn)擊登錄")
      
          def test1(self):
              print('3. 輸??戶名密碼驗(yàn)證碼1,點(diǎn)擊登錄 ')
      
          def test2(self):
              print('3. 輸??戶名密碼驗(yàn)證碼1,點(diǎn)擊登錄 ')
      
          def test3(self):
              print('3. 輸??戶名密碼驗(yàn)證碼1,點(diǎn)擊登錄 ')
      
          def tearDown(self) -> None:
              print("4.關(guān)閉網(wǎng)頁(yè)")
      
          @classmethod
          def tearDownClass(cls) -> None:
              print("5.關(guān)閉瀏覽器")
      
      

      DAY-10課堂筆記


      斷言

      使用代碼自動(dòng)的判斷預(yù)期結(jié)果和實(shí)際結(jié)果是否相符
      
      assertEqual(預(yù)期結(jié)果,實(shí)際結(jié)果)
      - 判斷預(yù)期結(jié)果和實(shí)際結(jié)果是否相等,如果相等, 用例通過(guò),如果不相等,拋出異常, 用例不通過(guò)
      
      assertIn(預(yù)期結(jié)果,實(shí)際結(jié)果)
      - 判斷預(yù)期結(jié)果是否包含在 實(shí)際結(jié)果中, 如果存在,用例通過(guò), 如果不存在,拋出異常,用例不通過(guò)
      
      import unittest
      class TestAssert(unittest.TestCase):
      	def test_equal_1(self):
      		self.assertEqual(10, 10) # 用例通過(guò)
      	def test_assert_2(self):
      		self.assertEqual(10, 11) # 用例不通過(guò)
      	def test_in(self):
              # self.assertIn('admin', '歡迎 admin 登錄') # 包含 通過(guò)
              # self.assertIn('admin', '歡迎 adminnnnnnnn 登錄') # 包含 通過(guò)
              # self.assertIn('admin', '歡迎 aaaaaadminnnnnnnn 登錄') # 包含 通過(guò)
              # self.assertIn('admin', '歡迎 adddddmin 登錄') # 不包含 不通過(guò)
      		self.assertIn('admin', 'admin') # 包含 通過(guò)
      
      import unittest
      
      from hm_02_assert import TestAssert
      
      suite = unittest.TestSuite()
      
      suite.addTest(unittest.makeSuite(TestAssert))
      unittest.TextTestRunner().run(suite)
      

      參數(shù)化

      - 通過(guò)參數(shù)的方式來(lái)傳遞數(shù)據(jù),從而實(shí)現(xiàn)數(shù)據(jù)和腳本分離。并且可以實(shí)現(xiàn)用例的重復(fù)執(zhí)行。(在書(shū)寫用例方法的時(shí)候,測(cè)
      試數(shù)據(jù)使用變量代替,在執(zhí)行的時(shí)候進(jìn)行據(jù)說(shuō)傳遞)
      - unittest 測(cè)試框架,本身不支持參數(shù)化,但是可以通過(guò)安裝unittest擴(kuò)展插 件 parameterized 來(lái)實(shí)現(xiàn)。
      

      使用

      1. 導(dǎo)包 from para... import para...
      2. 修改測(cè)試方法,將測(cè)試方法中的測(cè)試數(shù)據(jù)使用 變量表示
      3. 組織測(cè)試數(shù)據(jù),格式 [(), (), ()], 一個(gè)元組就是一組測(cè)試數(shù)據(jù)
      4. 參數(shù)化,在測(cè)試方法上方使用裝飾器 @parameterized.expand(測(cè)試數(shù)據(jù))
      5. 運(yùn)行(直接 TestCase 或者 使用 suite 運(yùn)行)
      
      import unittest
      
      from tools import add
      
      from parameterized import parameterized
      data = [(1, 1, 2), (1, 2, 3), (2, 3, 5), (4, 5, 9)]
      
      class TestAdd(unittest.TestCase):
          @parameterized.expand(data)
          
          
          def test_add(self, a, b, expect):
              print(f'a:{a}, b:{b}, expect:{expect}')
              self.assertEqual(expect, add(a, b))
              
              
      if __name__ == '__main__':
      	unittest.main()
      

      練習(xí)

      將測(cè)試數(shù)據(jù) 定義為 json 文件, 讀取 json 文件,完成參數(shù)化
      
      • json 文件

        [
            [1, 1, 2],
            [1, 2, 3],
            [2, 3, 5],
            [4, 5, 9],
            [10, 20, 30]
        ]
        
      • 讀取 json 文件

        import json
        
        
        def build_add_data():
            with open('add_data.json') as f:
           		data = json.load(f) # [[], [], []] ---> [(), ()]
                
                
            return data
        
        
      • 代碼文件

        import unittest
        
        
        from read_data import build_add_data
        from tools import add
        from parameterized import parameterized
        data = [(1, 1, 2), (1, 2, 3), (2, 3, 5), (4, 5, 9)]
        
        
        class TestAdd(unittest.TestCase):
            @parameterized.expand(build_add_data())
        	def test_add(self, a, b, expect):
                print(f'a:{a}, b:{b}, expect:{expect}')
        		self.assertEqual(expect, add(a, b))
                
                
        if __name__ == '__main__':
        	unittest.main()
        

      生成HTML測(cè)試報(bào)告


      使用第三方的報(bào)告模版,生成報(bào)告 HTMLTestReport, 本質(zhì)是 TestRunner
      
      
      - 安裝
      pip install -i https://pypi.douban.com/simple/ HTMLTestReport
      
      
      - 使用
      1. 導(dǎo)包 unittest、HTMLTestReport
      2. 組裝用例(套件, loader )
      3. 使用 HTMLTestReport 中的 runner 執(zhí)行套件
      4. 查看報(bào)告
      
      import unittest
      from htmltestreport import HTMLTestReport
      from hm_04_pa1 import TestAdd
      
      # 套件
      suite = unittest.TestSuite()
      suite.addTest(unittest.makeSuite(TestAdd))
      
      # 運(yùn)行對(duì)象
      # runner = HTMLTestReport(報(bào)告的文件路徑后綴.html, 報(bào)告的標(biāo)題, 其他的描述信息)
      runner = HTMLTestReport('test_add_report.html', '加法用例測(cè)試報(bào)告', 'xxx')
      runner.run(suite)
      

      使用絕對(duì)路徑

      將來(lái)的項(xiàng)目是分目錄書(shū)寫的, 使用相對(duì)路徑,可能會(huì)出現(xiàn)找不到文件的情況,此時(shí)需要使用 絕對(duì)路徑
      方法:
      1. 在項(xiàng)目的根目錄,創(chuàng)建一個(gè) Python 文件(app.py 或者 config.py)
      2. 在這個(gè)文件中 獲取項(xiàng)目的目錄,在其他代碼中使用 路徑拼接完成絕對(duì)路徑的書(shū)寫
      

      import os
      # __file__ 特殊的變量,表示當(dāng)前代碼文件名
      # path1 = os.path.abspath(__file__)
      # print(path1)
      # path2 = os.path.dirname(path1)
      # print(path2)
      # BASE_DIR = os.path.dirname(os.path.abspath(__file__))
      BASE_DIR = os.path.dirname(__file__)
      
      
      if __name__ == '__main__':
      	print(BASE_DIR)
      

      案例

      1, 對(duì)登錄函數(shù)進(jìn)行測(cè)試, 登錄函數(shù) 定義在 tools.py 中
      2, 在 case 目錄中書(shū)寫用例對(duì)login 函數(shù)進(jìn)行測(cè)試, 使用斷言
      3, 將 login 函數(shù)的測(cè)試數(shù)據(jù)定義在 json 文件中,完成參數(shù)化, data 目錄中
      4, 生成測(cè)試報(bào)告 report 目錄中
      
      #測(cè)試數(shù)據(jù)的json文件
      #login_data.json
      [
        {
          "desc": "正確的用戶名和密碼",
          "username": "admin",
          "password": "123456",
          "expect": "登錄成功"
        },
        {
          "desc": "錯(cuò)誤的用戶名",
          "username": "root",
          "password": "123456",
          "expect": "登錄失敗"
        },
        {
          "desc": "錯(cuò)誤的密碼",
          "username": "admin",
          "password": "123123",
          "expect": "登錄失敗"
        },
        {
          "desc": "錯(cuò)誤的用戶名和密碼",
          "username": "root",
          "password": "123123",
          "expect": "登錄失敗"
        }
      ]
      
      #讀取測(cè)試數(shù)據(jù)
      #read_data.py
      def build_login_data():
          with open(BASE_DIR + '/data/login_data.json', encoding='utf-8') as f:
              data_list = json.load(f)  # [{}, {}] ---> [()]
              new_list = []
              for data in data_list:
                  # 字典中的 desc 不需要
                  username = data.get('username')
                  password = data.get('password')
                  expect = data.get('expect')
                  new_list.append((username, password, expect))
      
              return new_list
      
      #Suite 報(bào)告代碼
      #login.py
      import unittest
      
      from app import BASE_DIR
      from case.test_login import TestLogin
      from htmltestreport import HTMLTestReport
      
      suite = unittest.TestSuite()
      suite.addTest(unittest.makeSuite(TestLogin))
      
      runner = HTMLTestReport(BASE_DIR + '/report/login_report.html', '登錄測(cè)試報(bào)告', 'V1.0')
      runner.run(suite)
      

      跳過(guò)

      跳過(guò):對(duì)于一些未完成的或者不滿足測(cè)試條件的測(cè)試函數(shù)和測(cè)試類,可以跳過(guò)執(zhí)行(簡(jiǎn)單來(lái)說(shuō), 不想執(zhí)行的測(cè)試方法,可以設(shè)置為跳過(guò))
      
      - 直接將測(cè)試函數(shù)標(biāo)記成跳過(guò)
      	@unittest.skip('跳過(guò)的原因')
      
      - 根據(jù)條件判斷測(cè)試函數(shù)是否跳過(guò)
      	@unittest.skipIf(判斷條件, reason='原因') # 判斷條件為 True, 執(zhí)行跳過(guò)
      
      import unittest
      
      version = 29
      
      
      class TestSkip(unittest.TestCase):
          @unittest.skip('沒(méi)什么原因,就是不想執(zhí)行')
          def test_1(self):
              print('方法一')
      
          @unittest.skipIf(version >= 30, '版本號(hào)大于等于 30, 測(cè)方法不用執(zhí)行')
          def test_2(self):
              print('方法二')
      
          def test_3(self):
              print('方法三')
      
      
      if __name__ == '__main__':
          unittest.main()
      

      DAY-09課堂筆記


      UnitTest基本使用

      UnitTest框架介紹

      • 框架

        什么是框架?
        1. 框架英文單詞framework
        2. 為解決一類事情的功能集合
        
      • UnitTest框架

        是Python自帶的一個(gè)單元測(cè)試框架
        - ?帶的, 可以直接使?, 不需要單外安裝
        - 測(cè)試?員 ?來(lái)做?動(dòng)化測(cè)試, 作為?動(dòng)化測(cè)試的執(zhí)?框架, 即 管理和執(zhí)??例的
        
      • 為什么使用UnitTest框架?

        1. 能夠組織多個(gè)用例去執(zhí)行
        2. 提供豐富的斷言方法
        3. 能夠生成測(cè)試報(bào)告
        
      • UnitTest 核心要素(組成)

        1. TestCase 測(cè)試?例, 這個(gè)測(cè)試?例是 unittest 的組成部分,作?是 ?來(lái)書(shū)寫真正的?例代碼(腳本)
        
        2. Testsuite 測(cè)試套件, 作?是?來(lái)組裝(打包)TestCase(測(cè)試?例) 的,即 可以將多個(gè)?例腳本?件 組裝到?起
        
        3. TestRunner 測(cè)試執(zhí)?(測(cè)試運(yùn)?), 作? 是?例執(zhí)?TestSuite(測(cè)試套件)的
        
        4. TestLoader 測(cè)試加載, 是對(duì) TestSuite(測(cè)試套件) 功能的補(bǔ)充, 作?是?來(lái)組裝(打包) TestCase(測(cè)試?例) 的
        
        5. Fixture 測(cè)試夾具, 是?種代碼結(jié)構(gòu), 書(shū)寫 前置?法(執(zhí)??例之前的?法)代碼 和后置?法(執(zhí)??例之后的?法) 代碼 ,即 ?例執(zhí)?順序 前置 ---> ?例 ---> 后置
        

      TestCase 測(cè)試?例

      書(shū)寫真正的?例代碼(腳本)
      單獨(dú)?個(gè)測(cè)試?例 也是可以執(zhí)?
      
      • 步驟:

        1. 導(dǎo)包 unittest
        2. 定義測(cè)試類, 需要繼承 unittest.TestCase 類, 習(xí)慣性類名以 Test 開(kāi)頭
        3. 書(shū)寫測(cè)試?法, 必須以 test 開(kāi)頭
        4. 執(zhí)?
        
      • 注意事項(xiàng)

        1. 代碼?件名字 要滿?標(biāo)識(shí)符的規(guī)則
        2. 代碼?件名 不要使?中?
        
      • 代碼

        # 1. 導(dǎo)包
        import unittest
        
        
        # 2. 定義測(cè)試類:新建 測(cè)試類 ;只要繼承unittest.TestCase類,就是測(cè)試類
        class TestDemo(unittest.TestCase):
        
            # 3. 定義測(cè)試方法:測(cè)試方法名稱命名必須以test開(kāi)頭
            def test_01(self):
                print("測(cè)試一")
        
            def test_02(self):
                print("測(cè)試二")
        
        # 4.執(zhí)行
        # 4.1 在類名或者?法名后邊右鍵運(yùn)?
        # 4.1.1 在類名后邊, 執(zhí)?類中的所有的測(cè)試?法
        # 4.1.2 在?法名后邊, 只執(zhí)?當(dāng)前的測(cè)試?法
        
        

      TestSuite 測(cè)試套件 和 TextTestRunner 測(cè)試執(zhí)?

      TestSuite(測(cè)試套件)

      將多條?例腳本集合在?起,就是套件, 即?來(lái)組裝?例的
      
      • 步驟

        1. 導(dǎo)包 unittest
        2. 實(shí)例化套件對(duì)象 unittest.TestSuite()
        3. 添加?例?法
        

      TextTestRunner 測(cè)試執(zhí)?

      ?來(lái)執(zhí)?套件對(duì)象
      
      • 步驟

        1. 導(dǎo)包 unittest
        2. 實(shí)例化 執(zhí)?對(duì)象 unittest.TextTestRunner()
        3. 執(zhí)?對(duì)象執(zhí)? 套件對(duì)象 執(zhí)?對(duì)象.run(套件對(duì)象)
        

      整體步驟

      1. 導(dǎo)包 unittest
      2. 實(shí)例化套件對(duì)象 unittest.TestSuite()
      3. 添加?例?法
      -  3.1 套件對(duì)象.addTest(測(cè)試類名('測(cè)試?法名'))
      4. 實(shí)例化 執(zhí)?對(duì)象 unittest.TextTestRunner()
      5. 執(zhí)?對(duì)象執(zhí)? 套件對(duì)象 執(zhí)?對(duì)象.run(套件對(duì)象)
      
      # 1. 導(dǎo)包 unittest
      import unittest
      from TestCase import TestDemo
      from TestCase_01 import TestDemo01
      
      # 2. 實(shí)例化套件對(duì)象 unittest.TestSuite()
      suite = unittest.TestSuite()
      # 3. 添加?例?法
      # -  3.1 套件對(duì)象.addTest(測(cè)試類名('測(cè)試?法名'))
      suite.addTest(TestDemo('test_01'))
      suite.addTest(TestDemo('test_02'))
      suite.addTest(TestDemo01('test_03'))
      suite.addTest(TestDemo01('test_04'))
      
      # -  3.2套件對(duì)象.addTest(unittest.makeSuite(測(cè)試類名)) # 在
      不同的 Python 版本中,可能沒(méi)有提示
      suite.addTest(unittest.makeSuite(TestDemo1))
      suite.addTest(unittest.makeSuite(TestDemo2))
      
      #  - 3.3
      suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestDemo1))
      suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestDemo2))
      
      # 4. 實(shí)例化 執(zhí)?對(duì)象 unittest.TextTestRunner()
      
      runner = unittest.TextTestRunner()
      # 5. 執(zhí)?對(duì)象執(zhí)? 套件對(duì)象 執(zhí)?對(duì)象.run(套件對(duì)象)
      runner.run(suite)
      

      TestLoader 測(cè)試加載

      作?和 TestSuite 作??樣,組裝?例代碼, 同樣也需要使?TextTestRunner() 去執(zhí)?
      
      需要使用10 個(gè)?例腳本 makeSuite()
      
      使用unittest.TestLoader,通過(guò)該類下面的discover()方法自動(dòng)搜索指定目錄下指定開(kāi)頭的.py文件,并將查找到的測(cè)試用例組裝到測(cè)試套件。
      

      步驟

      1. 導(dǎo)包 unittest
      2. 實(shí)例化加載對(duì)象并加載?例 ---> 得到的是 套件對(duì)象(最終返回的還是測(cè)試套件對(duì)象,運(yùn)行測(cè)試套件還需要使用TestRunner)
      3. 實(shí)例化執(zhí)?對(duì)象并執(zhí)?
      
      import unittest
      
      # 實(shí)例化加載對(duì)象并加載?例,得到套件對(duì)象
      # suite = unittest.TestLoader().discover('?例所在的?錄', '?例代碼?件名*.py')
      suite = unittest.TestLoader().discover("./", "hm_02*.py")
      
      # runner=unittest.TextTestRunner()
      # runner.run(suite)
      
      unittest.TextTestRunner().run(suite)
      

      練習(xí)

      1.

      1. 創(chuàng)建?個(gè)?錄 case, 作?就是?來(lái)存放?例腳本,
      2. 在這個(gè)?錄中創(chuàng)建 5 個(gè)?例代碼?件 , test_case1.py
      ...
      3. 使? TestLoader 去執(zhí)??例
      -----
      將來(lái)的代碼 ?例都是單獨(dú)的?錄 中存放的
      test_項(xiàng)?_模塊_功能.py
      
      import unittest
      
      suite = unittest.TestLoader().discover('case', 'test_case*.py')
      
      unittest.TextTestRunner().run(suite)
      

      2.

      1. 定義?個(gè) tools 模塊, 在這個(gè)模塊中 定義 add 的?法,可
      以對(duì)兩個(gè)數(shù)字求和,返回求和結(jié)果
      2. 書(shū)寫?例, 對(duì) add() 函數(shù)進(jìn)?測(cè)試
      1, 1, 2
      1, 2, 3
      3, 4, 7
      4, 5, 9
      -----
      之前的測(cè)試?法,直接?個(gè) print
      這個(gè)案例中的 測(cè)試?法,調(diào)? add 函數(shù), 使? if 判斷,來(lái)判斷
      預(yù)期結(jié)果和實(shí)際結(jié)果是否相符
      預(yù)期結(jié)果 2 3 7 9
      實(shí)際結(jié)果 調(diào)? add()
      
      import unittest
      from tools import add
      
      class testadd(unittest.TestCase):
          def test1(self):
              """1,1,2"""
              print(f"測(cè)試數(shù)據(jù)為:{1},{1},{2}")
              if 2==add(1,1):
                  print(f"測(cè)試數(shù)據(jù)為:{1},{1},{2}通過(guò)")
              else:
                  print(f"測(cè)試數(shù)據(jù)為:{1},{1},{2}不通過(guò)")
      
      
          def test2(self):
              """1,2,3"""
              print(f"測(cè)試數(shù)據(jù)為:{1},{2},{3}")
              if 3==add(1,2):
                  print(f"測(cè)試數(shù)據(jù)為:{1},{2},{3}通過(guò)")
              else:
                  print(f"測(cè)試數(shù)據(jù)為:{1},{2},{3}不通過(guò)")
      
      
          def test3(self):
              """3,4,7"""
              print(f"測(cè)試數(shù)據(jù)為:{3},{4},{7}")
              if 3==add(1,2):
                  print(f"測(cè)試數(shù)據(jù)為:{3},{4},{7}通過(guò)")
              else:
                  print(f"測(cè)試數(shù)據(jù)為:{3},{4},{7}不通過(guò)")
      
          def test4(self):
              """4,5,9"""
              print(f"測(cè)試數(shù)據(jù)為:{4},{5},{9}")
              if 3==add(1,2):
                  print(f"測(cè)試數(shù)據(jù)為:{4},{5},{9}通過(guò)")
              else:
                  print(f"測(cè)試數(shù)據(jù)為:{4},{5},{9}不通過(guò)")
      

      Fixture

      代碼結(jié)構(gòu), 在?例執(zhí)?前后會(huì)?動(dòng)執(zhí)?的代碼結(jié)構(gòu)
      tpshop 登錄
      1. 打開(kāi)瀏覽器 (?次)
      2. 打開(kāi)??,點(diǎn)擊登錄 (每次)
      3. 輸??戶名密碼驗(yàn)證碼1,點(diǎn)擊登錄 (每次, 測(cè)試?法)
      4. 關(guān)閉?? (每次)
      2. 打開(kāi)??,點(diǎn)擊登錄 (每次)
      3. 輸??戶名密碼驗(yàn)證碼2,點(diǎn)擊登錄 (每次, 測(cè)試?法)
      4. 關(guān)閉?? (每次)
      2. 打開(kāi)??,點(diǎn)擊登錄 (每次)
      3. 輸??戶名密碼驗(yàn)證碼3,點(diǎn)擊登錄 (每次, 測(cè)試?法)
      4. 關(guān)閉?? (每次)
      5. 關(guān)閉瀏覽器 (?次)
      

      方法級(jí)別Fixture

      在每個(gè)?例執(zhí)?前后都會(huì)?動(dòng)調(diào)?, ?法名是固定的
      
      def setUp(self): # 前置
       # 每個(gè)?例執(zhí)?之前都會(huì)?動(dòng)調(diào)?
       pass
      
      
      def tearDown(self): # 后置
       # 每個(gè)?例執(zhí)?之后 都會(huì)?動(dòng)調(diào)?
       pass
      # ?法前置 ?例 ?法后置
      # ?法前置 ?例 ?法后置
      

      類級(jí)別Fixture

      在類中所有的測(cè)試?法執(zhí)?前后 會(huì)?動(dòng)執(zhí)?的代碼, 只執(zhí)??次
      
      # 類級(jí)別的 Fixture 需要寫作類?法
      @classmethod
      def setUpClass(cls): # 類前置
       	pass
      
      
      @classmethod
      def tearDownClass(cls): # 后置
       	pass
      # 類前置 ?法前置 ?例 ?法后置 ?法前置 ?例 ?法后置類后置
      

      模塊級(jí)別Fixture(了解)

      模塊, 就是代碼?件
      模塊級(jí)別 在這個(gè)代碼?件執(zhí)?前后執(zhí)??次
      
      # 在類外部定義函數(shù)
      def setUpModule():
           pass
          
          
      def tearDownModule():
           pass
      
      實(shí)現(xiàn):
      tpshop 登錄
      1. 打開(kāi)瀏覽器 (?次)
      2. 打開(kāi)??,點(diǎn)擊登錄 (每次)
      3. 輸??戶名密碼驗(yàn)證碼1,點(diǎn)擊登錄 (每次, 測(cè)試?法)
      4. 關(guān)閉?? (每次)
      2. 打開(kāi)??,點(diǎn)擊登錄 (每次)
      3. 輸??戶名密碼驗(yàn)證碼2,點(diǎn)擊登錄 (每次, 測(cè)試?法)
      4. 關(guān)閉?? (每次)
      2. 打開(kāi)??,點(diǎn)擊登錄 (每次)
      3. 輸??戶名密碼驗(yàn)證碼3,點(diǎn)擊登錄 (每次, 測(cè)試?法)
      4. 關(guān)閉?? (每次)
      5. 關(guān)閉瀏覽器 (?次)
      
      import unittest
      
      
      class TestLogin(unittest.TestCase):
      
          @classmethod
          def setUpClass(cls) -> None:
              print("1.打開(kāi)瀏覽器")
      
          def setUp(self) -> None:
              print("2.打開(kāi)??, 點(diǎn)擊登錄")
      
          def test1(self):
              print('3. 輸??戶名密碼驗(yàn)證碼1,點(diǎn)擊登錄 ')
      
          def test2(self):
              print('3. 輸??戶名密碼驗(yàn)證碼1,點(diǎn)擊登錄 ')
      
          def test3(self):
              print('3. 輸??戶名密碼驗(yàn)證碼1,點(diǎn)擊登錄 ')
      
          def tearDown(self) -> None:
              print("4.關(guān)閉網(wǎng)頁(yè)")
      
          @classmethod
          def tearDownClass(cls) -> None:
              print("5.關(guān)閉瀏覽器")
      
      

      DAY-10課堂筆記


      斷言

      使用代碼自動(dòng)的判斷預(yù)期結(jié)果和實(shí)際結(jié)果是否相符
      
      assertEqual(預(yù)期結(jié)果,實(shí)際結(jié)果)
      - 判斷預(yù)期結(jié)果和實(shí)際結(jié)果是否相等,如果相等, 用例通過(guò),如果不相等,拋出異常, 用例不通過(guò)
      
      assertIn(預(yù)期結(jié)果,實(shí)際結(jié)果)
      - 判斷預(yù)期結(jié)果是否包含在 實(shí)際結(jié)果中, 如果存在,用例通過(guò), 如果不存在,拋出異常,用例不通過(guò)
      
      import unittest
      class TestAssert(unittest.TestCase):
      	def test_equal_1(self):
      		self.assertEqual(10, 10) # 用例通過(guò)
      	def test_assert_2(self):
      		self.assertEqual(10, 11) # 用例不通過(guò)
      	def test_in(self):
              # self.assertIn('admin', '歡迎 admin 登錄') # 包含 通過(guò)
              # self.assertIn('admin', '歡迎 adminnnnnnnn 登錄') # 包含 通過(guò)
              # self.assertIn('admin', '歡迎 aaaaaadminnnnnnnn 登錄') # 包含 通過(guò)
              # self.assertIn('admin', '歡迎 adddddmin 登錄') # 不包含 不通過(guò)
      		self.assertIn('admin', 'admin') # 包含 通過(guò)
      
      import unittest
      
      from hm_02_assert import TestAssert
      
      suite = unittest.TestSuite()
      
      suite.addTest(unittest.makeSuite(TestAssert))
      unittest.TextTestRunner().run(suite)
      

      參數(shù)化

      - 通過(guò)參數(shù)的方式來(lái)傳遞數(shù)據(jù),從而實(shí)現(xiàn)數(shù)據(jù)和腳本分離。并且可以實(shí)現(xiàn)用例的重復(fù)執(zhí)行。(在書(shū)寫用例方法的時(shí)候,測(cè)
      試數(shù)據(jù)使用變量代替,在執(zhí)行的時(shí)候進(jìn)行據(jù)說(shuō)傳遞)
      - unittest 測(cè)試框架,本身不支持參數(shù)化,但是可以通過(guò)安裝unittest擴(kuò)展插 件 parameterized 來(lái)實(shí)現(xiàn)。
      

      使用

      1. 導(dǎo)包 from para... import para...
      2. 修改測(cè)試方法,將測(cè)試方法中的測(cè)試數(shù)據(jù)使用 變量表示
      3. 組織測(cè)試數(shù)據(jù),格式 [(), (), ()], 一個(gè)元組就是一組測(cè)試數(shù)據(jù)
      4. 參數(shù)化,在測(cè)試方法上方使用裝飾器 @parameterized.expand(測(cè)試數(shù)據(jù))
      5. 運(yùn)行(直接 TestCase 或者 使用 suite 運(yùn)行)
      
      import unittest
      
      from tools import add
      
      from parameterized import parameterized
      data = [(1, 1, 2), (1, 2, 3), (2, 3, 5), (4, 5, 9)]
      
      class TestAdd(unittest.TestCase):
          @parameterized.expand(data)
          
          
          def test_add(self, a, b, expect):
              print(f'a:{a}, b:{b}, expect:{expect}')
              self.assertEqual(expect, add(a, b))
              
              
      if __name__ == '__main__':
      	unittest.main()
      

      練習(xí)

      將測(cè)試數(shù)據(jù) 定義為 json 文件, 讀取 json 文件,完成參數(shù)化
      
      • json 文件

        [
            [1, 1, 2],
            [1, 2, 3],
            [2, 3, 5],
            [4, 5, 9],
            [10, 20, 30]
        ]
        
      • 讀取 json 文件

        import json
        
        
        def build_add_data():
            with open('add_data.json') as f:
           		data = json.load(f) # [[], [], []] ---> [(), ()]
                
                
            return data
        
        
      • 代碼文件

        import unittest
        
        
        from read_data import build_add_data
        from tools import add
        from parameterized import parameterized
        data = [(1, 1, 2), (1, 2, 3), (2, 3, 5), (4, 5, 9)]
        
        
        class TestAdd(unittest.TestCase):
            @parameterized.expand(build_add_data())
        	def test_add(self, a, b, expect):
                print(f'a:{a}, b:{b}, expect:{expect}')
        		self.assertEqual(expect, add(a, b))
                
                
        if __name__ == '__main__':
        	unittest.main()
        

      生成HTML測(cè)試報(bào)告


      使用第三方的報(bào)告模版,生成報(bào)告 HTMLTestReport, 本質(zhì)是 TestRunner
      
      
      - 安裝
      pip install -i https://pypi.douban.com/simple/ HTMLTestReport
      
      
      - 使用
      1. 導(dǎo)包 unittest、HTMLTestReport
      2. 組裝用例(套件, loader )
      3. 使用 HTMLTestReport 中的 runner 執(zhí)行套件
      4. 查看報(bào)告
      
      import unittest
      from htmltestreport import HTMLTestReport
      from hm_04_pa1 import TestAdd
      
      # 套件
      suite = unittest.TestSuite()
      suite.addTest(unittest.makeSuite(TestAdd))
      
      # 運(yùn)行對(duì)象
      # runner = HTMLTestReport(報(bào)告的文件路徑后綴.html, 報(bào)告的標(biāo)題, 其他的描述信息)
      runner = HTMLTestReport('test_add_report.html', '加法用例測(cè)試報(bào)告', 'xxx')
      runner.run(suite)
      

      使用絕對(duì)路徑

      將來(lái)的項(xiàng)目是分目錄書(shū)寫的, 使用相對(duì)路徑,可能會(huì)出現(xiàn)找不到文件的情況,此時(shí)需要使用 絕對(duì)路徑
      方法:
      1. 在項(xiàng)目的根目錄,創(chuàng)建一個(gè) Python 文件(app.py 或者 config.py)
      2. 在這個(gè)文件中 獲取項(xiàng)目的目錄,在其他代碼中使用 路徑拼接完成絕對(duì)路徑的書(shū)寫
      

      import os
      # __file__ 特殊的變量,表示當(dāng)前代碼文件名
      # path1 = os.path.abspath(__file__)
      # print(path1)
      # path2 = os.path.dirname(path1)
      # print(path2)
      # BASE_DIR = os.path.dirname(os.path.abspath(__file__))
      BASE_DIR = os.path.dirname(__file__)
      
      
      if __name__ == '__main__':
      	print(BASE_DIR)
      

      案例

      1, 對(duì)登錄函數(shù)進(jìn)行測(cè)試, 登錄函數(shù) 定義在 tools.py 中
      2, 在 case 目錄中書(shū)寫用例對(duì)login 函數(shù)進(jìn)行測(cè)試, 使用斷言
      3, 將 login 函數(shù)的測(cè)試數(shù)據(jù)定義在 json 文件中,完成參數(shù)化, data 目錄中
      4, 生成測(cè)試報(bào)告 report 目錄中
      
      #測(cè)試數(shù)據(jù)的json文件
      #login_data.json
      [
        {
          "desc": "正確的用戶名和密碼",
          "username": "admin",
          "password": "123456",
          "expect": "登錄成功"
        },
        {
          "desc": "錯(cuò)誤的用戶名",
          "username": "root",
          "password": "123456",
          "expect": "登錄失敗"
        },
        {
          "desc": "錯(cuò)誤的密碼",
          "username": "admin",
          "password": "123123",
          "expect": "登錄失敗"
        },
        {
          "desc": "錯(cuò)誤的用戶名和密碼",
          "username": "root",
          "password": "123123",
          "expect": "登錄失敗"
        }
      ]
      
      #讀取測(cè)試數(shù)據(jù)
      #read_data.py
      def build_login_data():
          with open(BASE_DIR + '/data/login_data.json', encoding='utf-8') as f:
              data_list = json.load(f)  # [{}, {}] ---> [()]
              new_list = []
              for data in data_list:
                  # 字典中的 desc 不需要
                  username = data.get('username')
                  password = data.get('password')
                  expect = data.get('expect')
                  new_list.append((username, password, expect))
      
              return new_list
      
      #Suite 報(bào)告代碼
      #login.py
      import unittest
      
      from app import BASE_DIR
      from case.test_login import TestLogin
      from htmltestreport import HTMLTestReport
      
      suite = unittest.TestSuite()
      suite.addTest(unittest.makeSuite(TestLogin))
      
      runner = HTMLTestReport(BASE_DIR + '/report/login_report.html', '登錄測(cè)試報(bào)告', 'V1.0')
      runner.run(suite)
      

      跳過(guò)

      跳過(guò):對(duì)于一些未完成的或者不滿足測(cè)試條件的測(cè)試函數(shù)和測(cè)試類,可以跳過(guò)執(zhí)行(簡(jiǎn)單來(lái)說(shuō), 不想執(zhí)行的測(cè)試方法,可以設(shè)置為跳過(guò))
      
      - 直接將測(cè)試函數(shù)標(biāo)記成跳過(guò)
      	@unittest.skip('跳過(guò)的原因')
      
      - 根據(jù)條件判斷測(cè)試函數(shù)是否跳過(guò)
      	@unittest.skipIf(判斷條件, reason='原因') # 判斷條件為 True, 執(zhí)行跳過(guò)
      
      import unittest
      
      version = 29
      
      
      class TestSkip(unittest.TestCase):
          @unittest.skip('沒(méi)什么原因,就是不想執(zhí)行')
          def test_1(self):
              print('方法一')
      
          @unittest.skipIf(version >= 30, '版本號(hào)大于等于 30, 測(cè)方法不用執(zhí)行')
          def test_2(self):
              print('方法二')
      
          def test_3(self):
              print('方法三')
      
      
      if __name__ == '__main__':
          unittest.main()
      
      posted on 2024-07-29 19:14  xcq_cm  閱讀(35)  評(píng)論(0)    收藏  舉報(bào)
       
      主站蜘蛛池模板: 性一交一乱一乱一视频| 国产成人高清亚洲综合| 日韩精品中文字幕一线不卡| 国产高清自产拍av在线| 五月综合激情婷婷六月| 国产人妻精品午夜福利免费| 国产成人8X人网站视频| 亚洲熟妇国产熟妇肥婆| 国产精品线在线精品| 少妇人妻偷人精品系列| 国产一区二区在线激情往| 国产亚洲精品中文字幕| 成人性生交大片免费看r老牛网站| 朝鲜女子内射杂交bbw| 国产男人的天堂在线视频| 熟女系列丰满熟妇AV| 国产欧美精品一区aⅴ影院| 久久久久综合一本久道| 亚洲高清WWW色好看美女| 看免费的无码区特aa毛片| 免费观看一级欧美大| 亚洲精品无码久久一线| 欧美激烈精交gif动态图| 大战丰满无码人妻50p| 7878成人国产在线观看| 91高清免费国产自产拍| 熟妇人妻一区二区三区四区| 色综合激情丁香七月色综合| 桃花岛亚洲成在人线AV| 亚洲日本韩国欧美云霸高清| 2020国产欧洲精品网站| 97精品伊人久久大香线蕉APP | 黄网站色视频免费观看| 一个色综合亚洲热色综合| 久章草在线毛片视频播放| 少妇高潮水多太爽了动态图| 亚洲av无码一区二区三区网站| 久久久久免费看少妇高潮A片| 国产成人高清精品亚洲| 在线观看成人av天堂不卡| 国产精品久久久国产盗摄|