整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Pytest生成HTML測試報告 不懂一定要看

          Pytest生成HTML測試報告 不懂一定要看

          ytest-HTML是一個插件,pytest用于生成測試結果的HTML報告。

          兼容Python 2.7,3.6

          安裝方式:pip install pytest-html

          pip install pytest-html

          通過命令行方式,生成xml/html格式的測試報告,存儲于用戶指定路徑。插件名稱:pytest-html
          使用方法: 命令行格式:pytest --html=用戶路徑/report.html

          前置條件:

          1.文件路徑:

           pytest_html_report
               - - test_bcbx.py
               - - pytest.ini
          import pytest
          class Test_bcbx:
              def setup_class(self):
                  print("------->setup_class")
              def teardown_class(self):
                  print("------->teardown_class")
              def test_a(self):
                  print("------->test_a")
                  assert 1
              def test_bcbx(self):
                      print("------->test_bcbx")
                      assert 0 # 斷言失敗```
          
          

          運行方式:
          1.修改Test_App/pytest.ini文件,添加報告參數

          即:addopts=-s --html=./report.html
          # -s:輸出程序運行信息
          # --html=./report.html 在當前目錄下生成report.html文件
          若要生成xml文件,可將--html=./report.html 改成 --html=./report.xml
          2.命令行進入pytest_html_report目錄
          3.執行命令: pytest
          執行結果:
          1.在當前目錄會生成assets文件夾和report.html文件

          F:\pytest_test\pytest_html_report>pytest===================test session starts===============platform win32 -- Python 3.7.1, pytest-6.2.2, py-1.9.0, pluggy-0.13.1
          rootdir: F:\pytest_test\pytest_html_report, configfile: pytest.ini
          plugins: Faker-4.1.3, html-3.1.1, metadata-1.11.0
          collected 2 items                                                                                                                                                                     
          
          
          test_bcbx.py ------->setup_class
          ------->test_a
          .------->test_bcbx
          F------->teardown_class===============FAILURES============______________ Test_bcbx.test_bcbx _____________
          self=<pytest_test.pytest_html_report.test_bcbx.Test_bcbx object at 0x0000000003D2FCC0>
          
          
              def test_bcbx(self):
                      print("------->test_bcbx")
          >           assert 0
          E           assert 0
          
          
          test_bcbx.py:13: AssertionError
           ------------- generated html file: file://F:\pytest_test\pytest_html_report\report.html -------====================short test summary info==================FAILED test_bcbx.py::Test_bcbx::test_bcbx - assert 0============== 1 failed, 1 passed in 2.21s ========

          #軟件測試#

          、安裝

          XPath (XML Path Language) 是一門在 HTML\XML 文檔中查找信息的語言,可用來在 HTML\XML 文檔中對元素和屬性進行遍歷。

          pip install lxml

          二、使用案例

          from lxml import etree
          import requests
          import asyncio
          import functools
          import re
          import json
          
          house_info=[]
          
          '''異步請求獲取鏈家每頁數據'''
          async def get_page(page_index):
              headers={
                  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
              }
              request=functools.partial(requests.get, f'https://sh.lianjia.com/ershoufang/pudong/pg{page_index}/',
                                          headers=headers)
              loop=asyncio.get_running_loop()
              response=await loop.run_in_executor(None, request)
              return response
          
          '''使用xpath獲取房屋信息'''
          def get_house_info(html):
              title_list=html.xpath('//a[@data-el="ershoufang"]/text()')  # 房屋title
              house_pattern_list=html.xpath('//div[@class="houseInfo"]/text()')  # 房屋格局
              price_list=html.xpath('//div[@class="unitPrice"]/span/text()')  # 房屋單價
              location_list=html.xpath('//div[@class="positionInfo"]')  # 房屋位置信息
              total_list=html.xpath('//div[contains(@class,"totalPrice")]')  # 總價
          
              for index, item in enumerate(zip(title_list, house_pattern_list, price_list)):
                  location_item=location_list[index]
                  total_item=total_list[index]
                  house_info.append({
                      'title': item[0],
                      'house_pattern': item[1],
                      'price': item[2],
                      'location': location_item.xpath('./a[1]/text()')[0] + location_item.xpath('./a[last()]/text()')[0],
                      'total': total_item.xpath('./span/text()')[0] + total_item.xpath('./i[last()]/text()')[0]
                  })
          
          '''異步獲取第一頁數據,拿到第一頁房屋信息,并返回分頁總數和當前頁'''
          async def get_first_page():
              response=await get_page(1)
              #etree.HTML 將獲取到的html字符串轉為可操作的Element對象
              get_house_info(etree.HTML(response.text))
          
          if __name__=='__main__':
              asyncio.run(get_first_page())
          

          三、etree 模塊

          1. etree.Element(element_name, attrib=None, nsmap=None) 創建element對象
          from lxml import etree
          '''
          element_name:要創建的元素的名稱
          attrib:元素的屬性字典
          nsmap:命名空間映射字典,用于指定元素的命名空間
          '''
          element=etree.Element('div',attrib={'class':'test'},nsmap={"ns": "http://example.com/ns"})
          1. etree.SubElement(parent, element_name, attrib=None, nsmap=None) 創建子元素
          from lxml import etree
          '''
          parent:element對象
          element_name:要創建的元素的名稱
          attrib:元素的屬性字典
          nsmap:命名空間映射字典,用于指定元素的命名空間
          '''
          element=etree.Element('div', attrib={'class': 'test'}, nsmap={"ns": "http://example.com/ns"})
          span_element=etree.SubElement(element,'span')
          span_element.text='我是span'
          print(element.xpath('//div/span/text()'))
          1. etree.fromstring(text, parser=None,base_url=None) 將XML、HTML字符串解析為Element對象
          from lxml import etree
          
          '''
          text:解析的XML字符串
          parse:解析器對象,默認lxml.etree.XMLParser、lxml.etree.HTMLParser
          base_url: 基本URL,用于解析相對URL。如果HTML文檔中包含相對URL,解析器將使用base_url來將其轉換為絕對URL。如果未提供base_url,則相對URL將保持不變
          '''
          html_str='<div class="test"><span>我是span</span></div>'
          element=etree.fromstring(html_str)
          print(element.xpath('//div/span/text()'))
          1. etree.HTML(text, parser=None, base_url=None) 將HTML字符串解析為Element對象
          from lxml import etree
          
          '''
          xml_string:解析的XML字符串
          parse:解析器對象,默認lxml.etree.HTMLParser
          base_url: 基本URL,用于解析相對URL。如果HTML文檔中包含相對URL,解析器將使用base_url來將其轉換為絕對URL。如果未提供base_url,則相對URL將保持不變
          '''
          html_str='<div class="test"><span>我是span</span></div>'
          element=etree.HTML(html_str)
          print(element.xpath('//div/span/text()'))
          1. etree.XML(text, parser=None, base_url=None) 將XML字符串解析為Element對象
          from lxml import etree
          
          '''
          text:解析的XML字符串
          parse:解析器對象,默認lxml.etree.XMLParser
          base_url: 基本URL,用于解析相對URL。如果HTML文檔中包含相對URL,解析器將使用base_url來將其轉換為絕對URL。如果未提供base_url,則相對URL將保持不變
          '''
          html_str='<div class="test"><span>我是span</span></div>'
          element=etree.XML(html_str)
          print(element.xpath('//div/span/text()'))
          1. etree.parse(source, parser=None, base_url=None) 將XML、HTML字符串解析為ElementTree對象

          四、element 對象

          1. element.xpath(path) 執行xpath語法
          2. element.nsmap:獲取或設置元素命名空間映射
          3. element.attrib:獲取或設置元素屬性
          4. element.text:獲取或設置文本
          5. element.tag:返回對象名稱
          6. element.append(element) 向節點里面追加子節點
          7. element.insert(index,element) 向節點開始的某個位置添加子節點
          from lxml import etree
          
          element=etree.Element('div', attrib={'class': 'test'})
          span_element=etree.SubElement(element, 'span')
          span_element.text='我是span'append_child=etree.Element('div', attrib={'class': 'append'})
          append_child.text='我是append_child'insert_child=etree.Element('div', attrib={'class': 'insert'})
          insert_child.text='我是insert_child'element.append(append_child)
          element.insert(0,insert_child)
          print(element.xpath('//div/span/text()'))
          print(element.xpath('//div/div[@class="append"]/text()'))
          print(element.xpath('//div/div[@class="insert"]/text()'))
          1. element.find(xpath): 在元素的子樹中查找與XPath表達式匹配的第一個元素,并返回該元素。如果找不到匹配的元素,則返回None
          2. element.findall(xpath): 在元素的子樹中查找與XPath表達式匹配的所有元素,并返回一個列表
          3. element.get(attribute_name, default=None): 獲取元素的指定屬性的值
          4. element.set(attribute_name, value): 設置元素的指定屬性的值
          5. element.iter(tag=None): 迭代元素及其子元素,可選擇指定標簽進行過濾
          6. element.getparent(): 獲取元素的父元素
          7. element.getchildren(): 獲取元素的所有子元素
          8. element.getroottree(): 獲取包含元素的根元素的Tree對象

          五、elementTree 對象

          1. elementTree.root: 根元素的Element對象。可以通過訪問tree.root來獲取根元素。
          2. elementTree.getroot(): 獲取根元素的Element對象。與tree.root屬性相同,用于獲取根元素
          3. elementTree.find(path): 在整個文檔中查找具有指定路徑的第一個元素,并返回該元素的Element對象。路徑可以使用XPath表達式指定
          4. elementTree.findall(path): 在整個文檔中查找具有指定路徑的所有元素,并返回這些元素的列表。路徑可以使用XPath表達式指定
          5. elementTree.iterfind(path): 在整個文檔中迭代查找具有指定路徑的元素,并返回這些元素的迭代器。路徑可以使用XPath表達式指定
          6. elementTree.write(file, encoding=None, xml_declaration=None, pretty_print=False): 將整個文檔寫入文件。file參數可以是文件名或文件對象。encoding參數指定寫入文件時使用的字符編碼。xml_declaration參數指定是否寫入XML聲明。pretty_print參數指定是否以更易讀的格式寫入文檔
          7. elementTree.tostring(element, encoding=None, method="xml", pretty_print=False): 將指定元素及其子元素序列化為字符串。element參數是要序列化的元素。encoding參數指定字符串的字符編碼。method參數指定序列化的方法,可以是"xml"(默認)或"html"。pretty_print參數指定是否以更易讀的格式序列化。
          8. elementTree.parse(source, parser=None, base_url=None): 靜態方法,用于解析XML或HTML文檔并返回一個ElementTree對象。與etree.parse函數的用法相同

          六、parse 解析器對象

          1. lxml.etree.XMLParser: 用于解析XML文檔的默認解析器。它支持標準的XML解析,并提供了豐富的功能和選項,如命名空間支持、DTD驗證等。
          2. lxml.etree.HTMLParser: 用于解析HTML文檔的默認解析器。它專門針對HTML進行了優化,并具有處理HTML特性的功能,如自動修復破碎的標簽、處理實體引用等。
          3. lxml.etree.XMLPullParser: 一種事件驅動的解析器,用于逐行解析XML文檔。它提供了一個迭代器接口,可以逐行讀取和處理XML文檔。
          4. lxml.etree.HTMLPullParser: 一種事件驅動的解析器,用于逐行解析HTML文檔。它提供了一個迭代器接口,可以逐行讀取和處理HTML文檔。

          要使用sed、awk、grep等工具進行嘗試(這會導致不可預期的結果)。在許多情況下,你最好選擇使用支持XML數據的編程語言進行處理。如果必須使用shell腳本,有一些專門用于解析HTML和XML文件的工具可供使用。

          Lynx

          你可能知道Lynx是一個帶有極限限制的終端模式Web瀏覽器。確實如此,但它也是一個可編程的HTML解析器。它特別擅長從文檔中提取鏈接并將其打印出來:

          如果你想要包括圖像鏈接,請添加-image_links選項。現在,根據你的需求過濾鏈接應該相對簡單,因為每個鏈接都在單獨的一行上,沒有HTML標簽的干擾。

          $ lynx -dump -listonly -nonumbers http://mywiki.wooledge.org/
          http://mywiki.wooledge.org/EnglishFrontPage?action=rss_rc&unique=1&ddiffs=1
          http://mywiki.wooledge.org/EnglishFrontPage?action=edit
          http://mywiki.wooledge.org/EnglishFrontPage
          http://mywiki.wooledge.org/EnglishFrontPage?action=raw
          http://mywiki.wooledge.org/EnglishFrontPage?action=print
          http://mywiki.wooledge.org/EnglishFrontPage?action=AttachFile&do=view&target=Greg's-wiki.zip
          [...]
          

          你可能會認為wget在這方面也很好用,對吧?我的意思是,它有遞歸鏡像模式,所以顯然內部做了這種操作。祝你好運,試圖找到一種方法讓wget將URL打印出來而不是下載全部文件。

          我試著嘗試了一下,找到了一種方法。沒有經過充分測試。我們可以使用--rejected-log和始終匹配的--reject-regex參數。我們使用--spider選項以不保存文件的方式執行。

          $ wget -q --spider -r --rejected-log=rejected --reject-regex=^ http://mywiki.wooledge.org/
          $ cat rejected
          REASON  U_URL   U_SCHEME        U_HOST  U_PORT  U_PATH  U_PARAMS        U_QUERY U_FRAGMENT      P_URL   P_SCHEME        P_HOST  P_PORT  P_PATH  P_PARAMS        P_QUERY P_FRAGMENT
          REGEX   http%3A//mywiki.wooledge.org/moin_static198/common/js/common.js SCHEME_HTTP     mywiki.wooledge.org     80      moin_static198/common/js/common.js      http%3A//mywiki.wooledge.org/   SCHEME_HTTP     mywiki.wooledge.org     80                          
          REGEX   http%3A//mywiki.wooledge.org/moin_static198/modernized/css/common.css   SCHEME_HTTP     mywiki.wooledge.org     80      moin_static198/modernized/css/common.css                                http%3A//mywiki.wooledge.org/   SCHEME_HTTP     mywiki.wooledge.org     80                          
          REGEX   http%3A//mywiki.wooledge.org/moin_static198/modernized/css/screen.css   SCHEME_HTTP     mywiki.wooledge.org     80      moin_static198/modernized/css/screen.css                                http%3A//mywiki.wooledge.org/   SCHEME_HTTP     mywiki.wooledge.org     80                          
          REGEX   http%3A//mywiki.wooledge.org/moin_static198/modernized/css/print.css    SCHEME_HTTP     mywiki.wooledge.org     80      moin_static198/modernized/css/print.css                         http%3A//mywiki.wooledge.org/   SCHEME_HTTP     mywiki.wooledge.org     80                          
          REGEX   http%3A//mywiki.wooledge.org/moin_static198/modernized/css/projection.css       SCHEME_HTTP     mywiki.wooledge.org     80      moin_static198/modernized/css/projection.css                            http%3A//mywiki.wooledge.org/   SCHEME_HTTP     mywiki.wooledge.org     80                          
          [...]
          

          要將鏈接提取到標準輸出中:

          $ wget -q --spider -r --rejected-log=/dev/stdout --reject-regex=^ http://mywiki.wooledge.org/ | tail -n +2 | cut -f 2
          http%3A//mywiki.wooledge.org/moin_static198/common/js/common.js
          http%3A//mywiki.wooledge.org/moin_static198/modernized/css/common.css
          http%3A//mywiki.wooledge.org/moin_static198/modernized/css/screen.css
          http%3A//mywiki.wooledge.org/moin_static198/modernized/css/print.css
          http%3A//mywiki.wooledge.org/moin_static198/modernized/css/projection.css
          [...]
          

          xmllint

          xmllint是處理大多數XML的最佳選擇。不幸的是,使用它需要學習XPath,而我并不知道任何合理的XPath入門教程。以下是一些簡單的技巧。它們是使用以下輸入文件演示的:

          <staff>
          <person name="bob"><salary>70000</salary></person>
          <person name="sue"><salary>90000</salary></person>
          </staff>
          

          請注意,xmllint在輸出中不添加換行符。如果你用CommandSubstitution進行捕獲,這不是問題。但如果你在交互式shell中測試,這將很快變得很煩人。你可以考慮編寫一個包裝函數,例如:

          xmllint() { command xmllint "$@"; echo; }
          

          簡單技巧:

          1. 打印第一個salary標簽:
          $ xmllint --xpath 'string(//salary)' foo.xml
          70000
          
          1. 打印所有的salary標簽(請注意,以這種形式打印并不特別有用):
          $ xmllint --xpath '//salary/text()' foo.xml
          7000090000
          
          1. 計算person標簽的數量:
          $ xmllint --xpath 'count(//person)' foo.xml
          2
          
          1. 分別打印每個人的salary:
          $ xmllint --xpath '//person[1]/salary/text()' foo.xml
          70000
          $ xmllint --xpath '//person[2]/salary/text()' foo.xml
          90000
          
          1. 打印bob的salary:
          $ xmllint --xpath '//person[@name="bob"]/salary/text()' foo.xml 
          70000
          
          1. 打印第二個人的name:
          $ xmllint --xpath 'string(//person[2]/@name)' foo.xml
          sue
          

          Namespaces

          上述示例顯示,當你擁有一個不錯的XML解析器時,解析XML是相當容易的,但這違背了XML的目的,即讓每個人都感到痛苦。因此,一些聰明人引入了XML命名空間。

          一個典型的maven構建文件(稱為pom.xml)就是這樣的例子,大致如下:

          <project xmlns="http://maven.apache.org/POM/4.0.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                                http://maven.apache.org/xsd/maven-4.0.0.xsd">
            <modelVersion>4.0.0</modelVersion>
           
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>my-project</artifactId>
            <version>1.0-SNAPSHOT</version>
          </project>
          

          通常還會有幾百行用于依賴項,但我們來保持簡潔。

          根據前一章的示例,我們知道從該文件中提取版本只需使用xpath /project/version/text():

          $ xmllint --xpath '/project/version/text()' pom.xml
          XPath set is empty
          

          嗯,不是這樣的,因為作者聰明地為這個xmlns="http://maven.apache.org/POM/4.0.0"添加了一個默認命名空間,所以現在你首先必須指定確切的URL,然后才能指明要獲取的版本元素內部的文本。

          xmllint --shell

          xmllint的--xpath選項沒有辦法指定命名空間,所以它現在無法使用(除非你編輯文件并刪除命名空間聲明)。但其shell功能確實允許設置命名空間。

          xmllint --shell pom.xml << EOF
          setns ns=http://maven.apache.org/POM/4.0.0
          cat /ns:project/ns:version/text()
          EOF
          / > / >  -------
          1.0-SNAPSHOT
          / >
          

          耶!我們得到了版本號...外加一些來自xmllint shell的提示和廢話,之后必須將其刪除。

          xmlstarlet

          xmlstarlet對于這個任務來說稍微容易一些

          $ xmlstarlet sel -N ns=http://maven.apache.org/POM/4.0.0 -t -v /ns:project/ns:version -n pom.xml
          1.0-SNAPSHOT
          

          python

          Python也附帶了一個XML解析器,通常比xmllint和xmlstarlet更常用。它也可以以一種笨拙的方式處理命名空間。

          $ python -c 'import xml.etree.ElementTree as ET;print(ET.parse("pom.xml").find("{http://maven.apache.org/POM/4.0.0}version").text)'
          1.0-SNAPSHOT
          

          xsltproc

          xsltproc恰好在大多數Linux系統上安裝。例如提取播客的標題和URL:

          xslt() {
          cat << 'EOX'
          <?xml version="1.0"?>
          <x:stylesheet version="1.0" xmlns:x="http://www.w3.org/1999/XSL/Transform">
          <x:output method="text" />
          <x:template match="/">
          <x:for-each select="//item">
                  <x:text># </x:text>
                  <x:value-of select="./title/text()" /><x:text>
          <!-- newline --></x:text>
                  <x:value-of select="enclosure/@url" /><x:text>
          </x:text>
          </x:for-each>
          </x:template>
          </x:stylesheet>
          EOX
          }
          
          curl -s http://podcasts.files.bbci.co.uk/p02nq0lx.rss | xsltproc <(xslt) -
          



          如果你想學習如何編寫更加健壯和可靠的 Shell 腳本,減少生產環境中的錯誤和故障,那么關注我吧!我會分享 Shell 編程的最佳實踐和建議,幫助你提高 Shell 腳本的魯棒性和可維護性。如果你想深入了解 Shell 編程的實際應用和技巧,可以關注我的《Shell 腳本編程最佳實踐》專欄,里面有我在一線互聯網大廠的實際生產經驗和最佳實踐,幫助你高效完成各種自動化任務。


          主站蜘蛛池模板: 久久精品一区二区东京热| 精品无人区一区二区三区在线| 色妞AV永久一区二区国产AV| 无码人妻精品一区二区三区99仓本| 狠狠做深爱婷婷久久综合一区| 亚洲国产一区二区三区青草影视| 视频在线观看一区| 国模无码视频一区| 国产SUV精品一区二区四| 蜜桃臀无码内射一区二区三区| 少妇无码AV无码一区| 亚洲av片一区二区三区| 视频一区视频二区日韩专区| 女同一区二区在线观看| 在线观看日本亚洲一区| 国产91久久精品一区二区| 人体内射精一区二区三区| 日本在线一区二区| 无码精品人妻一区二区三区中| 亚洲免费视频一区二区三区| 一区二区精品在线观看| 爆乳熟妇一区二区三区| 国产精品免费一区二区三区| 亚洲一区二区三区在线播放| 成人一区二区免费视频| 国产在线精品一区免费香蕉| 国产熟女一区二区三区四区五区| 中文字幕一区二区视频| 久久se精品一区二区| 99精品一区二区免费视频| 亚洲天堂一区二区三区| 久久中文字幕无码一区二区| 欧洲精品码一区二区三区| 乱中年女人伦av一区二区| 国产成人精品无人区一区| 日本欧洲视频一区| 日韩一区二区三区射精| 亚洲AV无码一区二三区| 国产AV一区二区三区传媒| 精品国产AV一区二区三区| 国产a久久精品一区二区三区|