主頁 > 前端設計 > 學習筆記之軟體測驗2:基于Python的單元測驗方法(Testcase+Pytest)

學習筆記之軟體測驗2:基于Python的單元測驗方法(Testcase+Pytest)

2020-10-15 23:36:22 前端設計

前言

  • 文章比較詳細,建議先收藏
  • 下一步:專案的具體測驗
  • 有任何問題,評論區留言

單元測驗目錄

  • 單元測驗的目的
    • 單元測驗的由來
    • 單元測驗的優勢
  • Request模塊
    • Request模塊簡介
      • 介紹
      • 安裝
    • 請求方式以及回應
      • HTTP介面動詞說明
      • 查詢引數對應的request模塊中的請求方式
    • Request模塊使用(Httpbin.org)
  • Django單元測驗
    • 說明
    • 資料庫環境準備
    • Testcase
      • setUp和tearDown函式
      • assert斷言捕獲例外的方法
    • Client
      • 說明
      • 登錄測驗兩種實作方法
    • FactoryRequest
      • 簡介
      • 用戶中心登錄測驗
    • mock
      • 簡介
      • mock實操
  • Pytestest單元測驗
    • Pytest介紹
      • pytest是什么
      • pytest的優點
    • Pytest環境準備
      • 安裝
      • 組態檔
      • demo
      • 運行方式
    • Pytest相關函式使用
      • Pytest-assert+warning
      • Pytest-setup/teardown
      • Pytest-fixture
      • Pytest-mark
    • Pytest的插件
      • Pytest-html-生成測驗報告
      • Pytest-orderingrun-控制函式執行順序
      • Pytest-rerunfailures-重測驗失敗的用例
    • Yaml
      • Yaml是什么
      • PyYAML決議

單元測驗的目的

單元測驗的由來

在軟體測驗的發展程序中衍生的一種測驗方法,能夠更高效率、更簡潔地實作軟體系統的模塊化的測驗,

單元測驗的優勢

  • 極大程度上節約測驗時間
    復雜的互動場景中自動化地幫助自己測驗組件,更快速的定位錯誤代碼位置,
  • 測驗本身不僅是發現錯誤,更能預防錯誤
    測驗能夠協助開發以更清晰的思路認識自己的代碼問題,只有認識到代碼問題才能夠讓代碼優化,帶給客戶更優質的體驗,
  • 能夠讓代碼更加簡潔
    測驗后的代碼,邏輯更加清晰,能夠減少代碼冗余,

Request模塊

Request模塊簡介

介紹

一、說明

? Request模塊是一個模擬用戶在客戶端發送各種請求的基于HTTP協議的Python庫

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-P8V9rGXa-1602593196197)(C:\Users\Pine\Desktop\03.png)]

二、作用

  • 軟體測驗使用:腳本化發送請求并分析回傳資料是否例外
  • 爬蟲使用:模擬用戶腳本化自動采集網路資源

安裝

# 切換虛擬環境!!!  安裝鏡像源為清華園
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple 

請求方式以及回應

HTTP介面動詞說明

在這里插入圖片描述

查詢引數對應的request模塊中的請求方式

查詢引數所有請求方式->requests.get(params={})
請求體 json引數非get請求方式(post、put、delete)->requests.post(json={})
請求體 form引數非get請求方式(post、put、delete)->requests.post(data={})
引數傳遞方式requests 接收的關鍵引數名字
請求頭引數所有請求方式->requests.get(headers={})

Request模塊使用(Httpbin.org)

httpbin.org說明:之后的測驗案例都采用對這個網站進行請求的方案

  1. 作用:測驗HTTP的Request請求并回傳對應的Response資訊,適用于GET、POST各種請求介面
  2. 專案架構:基于Python的Flask框架 開源
  3. Github地址:https://github.com/Runscope/httpbin
  4. 官網:http://httpbin.org/
  • Get 請求

    import requests
    from requests import Request, Session
    
    # 1. 定義URL物件
    # url = 'http://www.meiduo.site:8080/'
    url = 'http://httpbin.org/get'
    # 2. 新建request物件 注意+請求方式
    response = requests.get(url)
    # 3. 檢查獲取的資料格式以及內容列印到一個檔案中
    with open('test1.html', 'w') as f:
        f.write(response.text)
        
    # 4. 可以列印response觀察物件型別
    print(type(response))
    # text方法默認列印的回傳資料的json格式
    print(response1.text)
    
    # 默認列印的是回傳資料二進制資料
    print(response1.content)
    # b'{\n  "args": {}, \n  "headers": {\n    "Accept": "*/*", \n    "Accept-Encoding": "gzip, deflate", \n    "Host": "httpbin.org", \n    "User-Agent": "python-requests/2.23.0", \n    "X-Amzn-Trace-Id": "Root=1-5f818280-636d615a13bf7f173724951b"\n  }, \n  "origin": "106.121.5.147", \n  "url": "http://httpbin.org/get"\n}\n'
    
    • 回傳結果展示
      在這里插入圖片描述
  • POST請求

    # 1. URL
    URL = 'http://httpbin.org/post'
    # 2. request物件
    json_dict = {
        'user': '吳亦凡'
    }
    # 傳入資料 data:表單資料  json:json資料
    # response = requests.post(URL, data=json_dict)
    # response = requests.get(url,params=json_dict)
    response = requests.post(URL, json=json_dict)
    # 3. 寫入檔案
    with open('test1.html', 'w', encoding='utf-8') as f:
        f.write(response.text)
    
    • 回傳結果
      在這里插入圖片描述
  • 回應物件相關屬性說明

    # 1.獲取回應物件的資料 text(requests 會使用其推測的文本編碼)->string型別
    response.text
    # 2.獲取回應物件的資料 content->bytes型別
    # decode() 將 bytes-> str
    response.content.decode()
    # 3.前端回傳狀態碼(無論資料是否驗證正確,都會回傳200狀態碼,測驗判斷不能用狀態碼)
    response.status_code
    # 4.前后端分離開發模式下,存在一個問題無論資料是否驗證正確,都會回傳200狀態碼,測驗判斷不能用狀態碼  
    # 測驗網站登錄功能,介面規定登錄成功回傳json->{'code':0 ,'msg':oK}
    # 4.1獲取回應物件的 json資料---json()
    response.json()
    # 5.獲取請求頭資訊
    response.requests.headers
    # 6.獲取回應頭資訊
    response.headers
    # =====防止被反爬添加請求頭的資訊====
    # 添加請求頭資訊
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36'
    }
    request.get(url, headers=headers)
    
  • Cookie請求

    cookie作用:1. 常用與用戶登錄后,登錄狀態資訊的保存 2. 快取一些其他資訊

    # ===方法1:request物件中攜帶cookies====
    # 1. url
    url = 'http://httpbin.org/cookies'
    # 2. 定義cookie值  dict:強制型別轉換
    cookies = dict(cokie_is='Richerd')
    # 3. response加上cookie值
    # response = requests.post(URL, data=cookies)
    response = requests.get(url, cookies=cookies)
    # print(response.text)
    # 4. 寫入檔案
    with open('test1.html', 'w', encoding='utf-8') as f:
        f.write(response.text)
        
    # ===方法2: 直接使用cookie中的RequestsCookieJar()===
    # 這里引入 request.cookie
    # 1.實體化cookie_jar物件
    jar = requests.cookies.RequestsCookieJar()
    # 2.設定cookie
    # jar.set(請求頭key值, value值, 域名, 路徑)
    jar.set('coo', 'zhenxiang', domain='httpbin.org', path='/cookies')
    # 3.url
    url = 'http://httpbin.org/cookies'
    # 4.獲取物件
    response = requests.get(url, cookies=jar)
    print(response.text)
    
  • Session請求

    seesion作用:和cookie類似用于保存一些資訊,但瀏覽器中往往存的是seesionid值,真正的session資訊存盤在資料庫中

    request模塊中Session和Cookie的請求登錄的區分

    • request.get()

    requests.get() 就可以發送請求, 但是 遇到涉及登錄的時候, 應該先發送登錄請求->登錄成功獲取cookies->可以去請求需要登錄認證的頁面

    * 1.login請求: 攜帶賬戶和密碼 response = requests.post(url, json=xxx)
    * 2.決議登錄成功的:cookie   = response.request._cookies
    * 3.登錄用戶中心請求 '/mytaobao...':requests.get('<https://i.taobao.com/my_taobao.htm?spm=xxxx', cookies=cookies)
    
    • session.get()
      • 1.先訪問的是login的請求-- 攜帶賬戶和密碼 response = session.post()
      • 2.再發送 info 請求 – session.get(‘info’)
    from requests import Session
    
    # 1.創建session物件
    s = Session()
    # 2.發送帶cookie的請求  用url設定一個cookie值 之后的cookie將會一直和session物件系結
    s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
    # 3.獲取cookie值 檢查是否獲取成功
    r = s.get("http://httpbin.org/cookies")
    print(r.text)
    
    
    # 1. 設定 用戶名和密碼  即設定session物件的auth屬性默認值
    s.auth = ('user', 'pass')
    # 2. 可以直接增加請求頭中資訊(在原有請求頭欄位中添加)
    s.headers.update({'test1': 'wangyibo'})
    # 3. 請求頭中再次以引數形式添加另一個請求頭資訊  并檢查請求頭中是否已經添加成功
    # 注意這里或默認auth之前添加的資訊也會一塊合并到請求頭中
    r = s.get('http://httpbin.org/headers', headers={'test2': 'yibowangzha'})
    print(r.text)
    
    • 回傳結果
      在這里插入圖片描述

Django單元測驗

注意!:Django每次測驗每次測驗之前會自動創建一個和專案默認資料庫名稱相同的default臨時資料庫,而且臨時資料庫是復制了專案所有的表但是沒有資料,測驗用例測驗結束后,會把臨時創建的default資料庫洗掉

說明

  • Django的單元測驗模塊繼承自Python自帶的測驗基類unittest
  • postman和unitest的區別
    • Postman適用于介面測驗 —>黑盒測驗
    • unitest適用于代碼邏輯測驗 —>白盒測驗

資料庫環境準備

在Django的settings組態檔中進行對測驗資料庫配置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  
        'HOST': '127.0.0.1', 
        'PORT': 3306,  
        'USER': 'root',  
        'PASSWORD': 'mysql',  
        'NAME': 'mysql',
        'OPTION': {'charset': 'utf8'},
      
       # 配置測驗的資料庫
       # 1.單元測驗需要使用的資料庫,測驗執行時,會自動創建新的default資料庫包含TEST庫 
       # 2.每次自動創建的資料庫中沒有測驗資料,而且測驗執行完會自動洗掉測驗資料庫
       # 3.如果和default配置相同,使用默認配置
        'TEST':{
          'NAME':'test',
          'CHARSET': 'utf8',  # 設定測驗資料庫的字符集
          'COLLATION': 'utf8_general_ci',  # 測驗資料表中的行的編碼 
        }, 
    },
}

Testcase

注意事項!!!

  1. 由于使用的是Django自帶的測驗模塊,所以所有的測驗代碼都必須在專案的目錄下,且為Python的package
  2. 創建的測驗函式函式名組成格式 test_xxx
  3. 執行方式為終端執行 python manage.py test 默認一鍵執行所有的測驗代碼
  • 執行摸個應用的測驗 python manage.py 應用名
  • 執行應用下的某個測驗檔案 python manage.py 應用名.test_xxx
  • 執行應用下測驗檔案中的具體測驗類 python manage.py 應用名.test_xxx.Demotest
  • 具體到函式 執行應用下測驗檔案中的具體測驗類 python manage.py 應用名.test_xxx.Demotest.test_xxx

setUp和tearDown函式

  • setUp tearDown

    setUp 和 tearDown函式作用就是在測驗用例代碼執行前/后 做一些準備動作 !!!每個測驗用例執行前后都會執行

    使用場景:測驗之前打開檔案 測驗之后關閉檔案

    class TestDemo(TestCase):
    
        def setUp(self):
            print('---setup---')
    
        def tearDown(self) -> None:
            print('---tearDown---\n')
    
        def test_two(self):
            print('---222---')
    
        def test_three(self):
            print('---3333---')
    
        def test_four(self):
            print('---4444---')
    
    
    class TestDemo2(TestCase):
    
        def test_two(self):
            print('\n---TestDemo---')
    

    測驗結果:

    ---setup---
    ---4444---
    ---tearDown---
    
    ---setup---
    ---3333---
    ---tearDown---
    
    ---setup---
    ---222---
    ---tearDown---
    
    
    ---TestDemo---
    
    
  • @classmthod修飾

    setUpclass 和 tearDownclass 函式在這個類中的所有測驗用例執行前后只會執行一次

    使用場景:測驗用例測驗之前資料庫中添加測驗資料

    class ThreeTest(TestCase):
    
        @classmethod
        def setUpClass(cls):
            print('setUpClass--每個測驗用例類---呼叫一次')
    
        @classmethod
        def tearDownClass(cls):
            print('tearDownClass---每個測驗用例類---呼叫一次')
    
        def test_baidu(self):
            url = 'http://www.baidu.com'
            response = requests.get(url)
            print(response.status_code)
    
        def test_tencent(self):
            url = 'http://www.tencent.com'
            response = requests.get(url)
            print(response.status_code)
    

    回傳結果:

    setUpClass--每個測驗用例類---呼叫一次
    200
    200
    tearDownClass---每個測驗用例類---呼叫一次
    
  • 登錄測驗

    class LoginTest(TestCase):
    
        def test_login(self):
            url = 'http://www.heiheihei.site:8000/login/'
            json_dict = {'username': 'wangyibo', 'password': '12345678'}
            response = requests.post(url, json=json_dict)
            print(response.content.decode())
            
        
    # 登錄成功回傳json字串
    {"code": 0, "errmsg": "ok"}
         
    

assert斷言捕獲例外的方法

# assert 是一個python的關鍵字  作用是捕獲例外  詳細說明查看 https://blog.csdn.net/fengtian12345/article/details/80529510

# 正常使用assert函式
assert (1+1==2)
assert (1+1==3)  # 條件為 false時觸發  AssertionError 例外


# 測驗中使用到的 assert語法   self
self.assert(用于判斷的變數,判斷值,'如果不符合條件的提示')

Django的TestCase中封裝的assert方法:
在這里插入圖片描述

Client

說明

  1. client 自帶login方法 和session類似可以在client物件在被銷毀之前一直攜帶登錄的cookie

  2. client的login不用url地址

  3. client和session發送請求的區別

    session發送的真請求 client發送的偽請求(專案不用運行,直接測驗代碼)

登錄測驗兩種實作方法

unicode-escape編碼集 長這樣b``'\\u4e2d\\u56fd'

# ===================方法1:不使用login方法==================
class LoginTestCase(TestCase):
    def setUp(self):
        # 準備資料庫資料  加一個用戶
        User.objects.create_user(username='liudehua', password='11111111')
        self.client = Client()

    def test_login(self):
        # 1.介面url
        url = '/login/'
        # 2.設定登錄用戶
        json_dict = {'username': 'liudehua', 'password': '11111111'}
        # 3.用client物件進行 post登錄訪問測驗  添加content_type='application/json' 確保向后臺回傳json字串資料
        response = self.client.post(url, data=json_dict, content_type='application/json')
        # 4.檢查回傳資料  是否登陸成功
        print(response.content.decode())
        # 5.由于回傳json資料可能含有其他資料 我們這里只取后臺回傳的狀態碼code
        # 為斷言判斷取值
        code = json.loads(response.content.decode()).get('code')
        # 6.斷言函式 如果code為0則登錄成功  否則輸出‘登錄失敗'
        self.assertEqual(code, 0, '登錄失敗')
        
# =================方法2:使用login函式====================
class LoginTestCase(TestCase):
    def setUp(self):
        # 準備資料庫資料  加一個用戶
        User.objects.create_user(username='wangyibo', password='11111111')
        self.client = Client()

    def test_login(self):
        # 1.使用login函式直接發送請求
        login_result = self.client.login(request='post', username='wangyibo', password='11111111')
        # 登錄成功回傳True  失敗False
        print(login_result)
        # 2.使用斷言函式直接判斷是否登錄成功
        self.assertEqual(login_result, True, '登錄失敗')
        # 3.登錄成功訪問個人中心(檢查cookie攜帶)
        response = self.client.get('/info/')
        # 4.再使用斷言判斷是否訪問成功
        code = json.loads(response.content.decode())['code']
        print(response.content.decode())
        # 檢查cookie資訊
        print('登錄成功之后的cookie:', self.client.cookies)
        # 判斷
        self.assertEqual(code, 0, '個人中心訪問失敗!')

    def tearDown(self) -> None:
        # 退出登錄
        self.client.logout()
        # 檢查退出登錄之后的cookie值是否還在
        print('退出之后的cookie', self.client.cookies)

FactoryRequest

簡介

  • 注意事項

    • 只接受get post put delete head options 和trace 方法,這些方法接受的引數大部分相同, 因為它們只是用來生成請求
    • 它不支持中間件,會話和身份驗證屬性必須由測驗本身提供(如果需要)才能使視圖正常作業
  • 作用

    模擬一個請求物件,直接可以把請求物件傳給指定的視圖函式(作為引數),不需要手動指定url地址,

  • 原理

    # 類視圖:類名稱.as_view()(請求物件)
    # 視圖函式:視圖函式(請求物件)
    
    python manage.py shell
    # shell中匯入
    from django.http import HttpRequest
    from apps.users.views import LoginView
    # 發送請求  登錄介面實作
    request = HttpRequest()
    request.method='post'
    request.url = '/login/'
    
    # response = LoginView().post(request)
    response = LoginView.as_view()(request)
    print(response.content)
    

用戶中心登錄測驗

class LoginInfoTestCase(TestCase):

    def setUp(self) -> None:
        # 實體化物件屬性
        self.factory_request = RequestFactory()
        # 創建用戶
        self.user = User.objects.create_user(
            username='dilireba',
            password='12345678',
        )

    def test_info(self):
        # get方式請求用戶中心 創建factory物件
        factory_request = self.factory_request.get('/info/')
        # 攜帶用戶屬性 為登錄成功
        factory_request.user = self.user
        # 用factory模擬物件訪問用戶中心視圖函式
        response = UserInfoView.as_view()(factory_request)
        print(response.content.decode())
        # 斷言檢查是否進入成功
        code = json.loads(response.content.decode()).get('code')
        self.assertEqual(code, 0, '訪問個人中心失敗!')

mock

簡介

  • 概念

    注意:老django版本中有這個模塊 后來直接封裝到python庫了

    導包方式

    django < 2.0版本 from django.test import mock
    django > 2.0 版本 from unnitest import mock

    Mock是Python中一個用于支持單元測驗的庫,它的主要功能是使用mock物件替代掉指定的用于發送請求的物件,以達到模擬物件的行為,

  • 實作效果

    import requests
    
    def c(url):
        response = requests.get(url)
    

    mock實作程序:

    使用一個mock物件替換掉上面的requests.get函式,然后執行函式c時,c呼叫requests.get的回傳值就能夠由我們的mock物件來決定(若C函式執行成功<不用管具體的函式執行邏輯>接收函式回傳值,若不成功mock物件賦予默認值),而不需要服務器的參與

  • 適用場景

    • 在專案開發程序中,盡早介入測驗->先把基本功能的輸入輸出測驗,
    • 專案開發差不多,但是服務器架設進度緩慢,可以代替與服務器互動程序,提早測驗

mock實操

  • mock函式常用兩個引數說明

    • side_effect 表示被呼叫的函式名
      • 指向一個可呼叫的物件,一般是函式.當mock物件被呼叫時,如果該函式回傳值不是DEFAULT時,那么以該函式的回傳值作為mock物件呼叫的回傳值,
      • 是例外類或者物件時,當mock被呼叫就會被拋出,
      • 若是可迭代物件,mock每次呼叫就會回傳下一個值,若可迭代物件的元素是例外,就會拋出,
    • return_value 表示被呼叫的函式失效情況下的回傳值
    • 如果被呼叫的函式,功能暫未實作,可以通過return_value指定默認的回傳值,用來在測驗用例中進行斷言判斷
  • mock 小案例

    1. mock基礎使用

    # ==============被測驗的功能模塊===========
    
    mport requests
    # side_effect 表示被呼叫的函式名
    
    # return_value 表示被呼叫的函式的回傳值
    
    # B功能->發請求
    def send_req(url):
        print('B 功能....呼叫!')
        resp = requests.get(url)
        return resp.status_code
        pass
    
    
    # A功能->呼叫B
    def post_func():
        return send_req('http://www.baidu.com')
        pass
    
    # =============測驗上述模塊:兩種情況======================
    
    from . import utils
    from unittest import mock
    from django.test import TestCase
    
    class MockTestCase(TestCase):
        
        def test_B_None(self):
            """ 如果B模塊功能未實作"""
            # 1. 實體化mock物件 由于B功能未實作side_effect=None
            mock_obj = mock.Mock(side_effect=None, return_value=200)
            # 2. 替換send_req模塊 假設被post_func呼叫
            utils.send_req = mock_obj
            # 3. 獲取回傳結果  因為設定了 return_value=200 所以回傳結果應該是200
            results = utils.post_func()
            # 4. 斷言檢查是否為200
            self.assertEqual(results, 200, 'B模塊測驗失敗!')
        
        def test_B_function(self):
            """如果B模塊實作"""
            
            # 1.實體化  mock物件  由于B功能實作side_effect=utils.send_req
            mock_obj = mock.Mock(side_effect=utils.send_req, return_value=300)
            # 2.替換 send_req 模塊
            utils.send_req = mock_obj
            # 3. 獲取回傳結果  如果A功能呼叫B模塊成功 則回傳訪問baidu成功的狀態碼200
            results = utils.post_func()
            # 4. 斷言
            self.assertEqual(results, 200, 'B模塊測驗失敗!')
    

    2. mock 檢查是否被呼叫方法

    class TestMockCalled(TestCase):
        def test_func(self):
            # 1.新建mock物件
            mock_obj = mock.Mock(side_effect=utils.send_req, return_value=400)
            # 2.使用mock物件替換功能B函式
            utils.send_req = mock_obj
            # 3.測驗功能B函式訪問百度是否成功
            utils.visit_func()
            # 4.斷言mock物件是否被呼叫
            self.assertEqual(mock_obj.called, True)
            #  call('http://www.itcast.cn')
            self.assertEqual(mock_obj.call_args, True)
            #  [call('http://www.itcast.cn')]
            self.assertEqual(mock_obj.call_args_list, True)
    

    3. mock 背景關系管理器用法

    # ======測驗一個登陸功能的介面視圖函式是否可以正常被呼叫=======
    
    class LoginMockTest(TestCase):
        def test_class(self):
            """模擬類視圖1"""
            # 實體化mock物件
            mock_obj = mock.Mock(return_value=200)
            # mock替換
            LoginView.post = mock_obj
            print('>>>test_class run>>>')
            self.assertEqual(LoginView.post(), 200)
    
        def test_context_mock_use(self):
            # 1.實體化 模擬物件
            mock_obj = mock.Mock(return_value=200)
            # 2.使用背景關系管理器實作視圖具體函式功能測驗
            # 引數1表示被測驗的類,引數2表示測驗類中的方法,引數3表示mock物件
            with mock.patch.object(LoginView, 'post', mock_obj):
                # 3.呼叫視圖函式  此時已經被mock物件替換
                results = LoginView.post()
                print(results)
                # 4.斷言判斷 post方法是否可以呼叫
                self.assertEqual(results, 200, '登錄失敗!')
    

    4. mock的裝飾器用法

    • reverse反向決議函式在django中的使用

      # 路由正向
      客戶端發請求->url->總路由->子路由->視圖函式
      # 路由反向
      視圖函式->路由
      
      # 使用reverse的前提
      # 1. 總路由需要起名稱  在使用的時候直接使用路由名稱即可
       path('', include(('apps.xxx.urls'),namespace="這個總路由的名"))
      # 2. 子路由起名
      path('login/', views.LoginView.as_view(), name='子路由的名'),
      # 3. 呼叫方法
      reverse('總路由名稱:子路由明名稱')
      # 4. 后端重定向用法
      redirect(reverse())
      
    • 裝飾器形式的mock測驗用戶登錄

      class ReverseTest(TestCase):
      
          def setUp(self) -> None:
              self.client = Client()
              self.url = reverse('User:Login')
              User.objects.create_user(username='wangyibo', password='11111111')
      
          # mock 裝飾器 寫法
          # @mock.patch('精確模塊的路徑')
          @mock.patch('apps.users.views.LoginView')
          def test_mock_decorator_order(self, mock_obj):
              # 1.接收 mock物件
              results = mock_obj
              # 2.指定 mock物件添加return_value屬性值
              results.post.return_value = 200
              # 3.添加測驗用戶
              data_dict = {'username': 'wangyibo', 'password': '11111111'}
              # 4. 測驗用 client 發送請求 測驗  注意測驗的測驗物件是被mock替代了的視圖函式 side_effect=登錄的視圖函式
              response = self.client.post(self.url, data=data_dict, content_type='application/json')
              print(response)
              # 4. 斷言
              self.assertEqual(response.status_code, 200, '測驗失敗!')
      
          def test_reverse_url(self):
              # 反向決議輸出檢查
              order_url = reverse('User:Login')
              print('反向決議的路由:', order_url)
      

Pytestest單元測驗

Pytest介紹

pytest是什么

  • 是python的一個用于測驗的框架
  • 適用于任何級別、任何代碼的測驗

pytest的優點

  • 命令列模式工具,撰寫測驗用例簡單,豐富的檔案參考
  • 支持單元測驗和功能測驗還有assert斷言 支持運行由Unittest撰寫的測驗Case
  • 支持跳過某些測驗,對某些預期失敗的case標記為失敗
  • 第三方插件豐富,可自定義
  • 支持引數化

Pytest環境準備

安裝

# !!!最好切換到虛擬環境
workon xxx
pip install pytest

組態檔

pytest的組態檔通常放在測驗目錄下,名稱為pytest.ini,命令運行時會使用該組態檔中的配置

[pytest]

# 1.給 pytest  傳引數  三個插件的組態檔中寫寫法如下
# -s 輸出測驗用例中的print內容  
# --html 插件 將測驗結果輸出為報告網頁  
# --rerun碰見測驗報錯重新測驗幾遍
addopts = -s --html=./a.html --reruns 3

# 2.指定 測驗腳本的 路徑
testpaths = ./

# 3.指定 測驗檔案的 名字
python_files = test_a*.py

# 4.指定 測驗檔案類的 名字  當前的目錄下有指定名稱檔案才會執行
python_classes = Test*

# 5.指定 測驗檔案函式的 名字
python_functions = test_*

demo

# 檔案名    test_demo.py  

import pytest
import requests


def test_one():
    r = requests.get('http://baidu.com')
    assert r.status_code == 200


def test_two():
    r = requests.get('http://baidu.com')
    assert r.encoding == 'utf'

# ======運行結果======
# 第一個測驗無報錯   第二個報錯 結果為 ISO-8859-1 != utf

運行方式

都是在終端環境下運行如下命令

  • pytest -s 運行當前目錄下的 所有測驗用例

    • -s 作用 就是 如果測驗用例通過, 測驗函式中的print輸出列印內容
  • pytest test_xx.py 執行 test_xx.py檔案 中 所有測驗用例

  • pytest test_xx.py::類::函式 執行具體的某個測驗用例

  • pytest.main([’-s’]) 腳本執行

    import pytest
    
    if __name__ == '__main__':
        pytest.main(['test_1.py','-s'])
    

Pytest相關函式使用

Pytest-assert+warning

  • 原生斷言

    import requests
    
    
    def test_assert():
        age = 20
    
        # 判斷 年齡是不是大于18歲
    
        assert age >= 18, '未成年!'
    
    
    def test_jingdong():
        response = requests.get('http://www.jd.com')
    
        print(response.content.decode())
    
        assert response.status_code == 202, '沒成功'
    

- 例外測驗

  # ====================測驗案例:判斷平年閏年================
  def is_leap_year(year):
  
      # 先判斷year是不是整型
      if isinstance(year, int) is not True:
          raise TypeError("傳入的引數不是整數")
  	# year 不能為0 的取值例外
      elif year == 0:
          raise ValueError("公元元年是從公元一年開始!!")
  	# year 必須為正整數的  型別例外
      elif abs(year) != year:
          raise ValueError("傳入的引數不是正整數")
  	# year的平潤年判斷
      # 以下代碼  和 例外型別 無關
      elif (year % 4 ==0 and year % 100 != 0) or year % 400 == 0:
          print("%d年是閏年" % year)
          return True
      else:
          print("%d年不是閏年" % year)
          return False
  # 一定要注意的是:站在測驗的角度去寫代碼   
  # 我們測驗報錯是否在業務邏輯中實作  而不是要看到測驗的報錯資訊  如果測驗OK不會有報錯的
  
  # =================raise()方法的使用================
  class TestException():
  
      def test_ValueError1(self):
          with pytest.raises(ValueError):
              utils.is_leap_year(-5)
  
      def test_TypeError(self):
          with pytest.raises(TypeError) as info:
              utils.is_leap_year(6.6)
          # 這里也可以搭配 assert方法提示報錯資訊
          assert info.type == TypeError
  
      def test_ValueError2(self):
          # match對應的錯誤資訊 因為數值錯誤有兩個 可能會匹配到其中任意一個
          # 如果 例外型別 相同 對比不出來, 需要借助例外中的提示資訊 二次
          # match的實作底層借用 re.search() 方法  尋找符合條件的字串提示資訊進行具體的錯誤型別匹配
          with pytest.raises(ValueError, match="公元元年"):
              utils.is_leap_year(0)
  
      def test_ValueError3(self):
          with pytest.raises(ValueError, match="正整數"):
              utils.is_leap_year(-9)
  
      def test_leap_year(self):
          assert utils.is_leap_year(2001) == True, "不是閏年"
  

- 警告測驗

  # =================測驗案例:幾個警告的提示函式=============
  class MakeWarns():
      # 1. 棄用警告 函式
      def make_decotat_warns(self):
          warnings.warn('deprecate', DeprecationWarning)
  
      # 2. 用戶警告 函式
      def make_user_warns(self):
          warnings.warn('user', UserWarning)
  
      # 3. 語法警告 函式
      def make_syntax_warns(self):
          warnings.warn('syntax', SyntaxWarning)
  
      # 4. 位元組警告 函式
      def make_bytes_warns(self):
          warnings.warn('bytes', BytesWarning)
  
      # 5. 運行時 runtime警告 函式
      def make_runtime_warns(self):
          warnings.warn('runtime', RuntimeWarning)
  
      # 6. 無警告 函式
      def not_warns(self):
          pass
  	# 7. 很多警告
      def many_warns(self):
          warnings.warn('runtime', RuntimeWarning)
          warnings.warn('user', UserWarning)
  
  # ===================測驗用例============
  import warning
  
  class TestWarnsType():
  
      def test_deprecate(self):
          # 測驗棄用警告
          with pytest.warns(DeprecationWarning):
              MakeWarns().make_decotat_warns()
  
      def test_bytes(self):
          # 測驗位元組警告
          with pytest.warns(BytesWarning):
              MakeWarns().make_bytes_warns()
  
      def test_sync(self):
          # 測驗語法警告
          with pytest.warns(SyntaxWarning, match='syntax'):
              MakeWarns().make_syntax_warns()
  
      def test_many_warning(self):
          # 測驗 很多警告 中Runtime是否生效
          with pytest.warns(RuntimeWarning) as record:
              MakeWarns().many_warns()
                
      def test_as(self):
          """warning的幾個資訊查看用法"""
          with pytest.warns(UserWarning) as warninfo:

            make_warning.warn_message()

          print('\n', warninfo)
          print(len(warninfo))
          print(warninfo[0].message)
          print(warninfo[1].message)

          assert len(warninfo) == 2
          assert str(warninfo[0].message) == "user"
          assert str(warninfo[1].message) == "runtime"

Pytest-setup/teardown

類似于django的Teatcase中的setUp和tearDown函式

一、函式分類及介紹

  • 函式級別
    • setup_function和teardown_function
      • 只針對測驗類 外面的 測驗函式 每個函式執行前后都會執行
    • setup_method和teardown_method
      • 只針對測驗類 里面的 測驗函式 類中每個函式執行前后都會執行
    • setup_class和teardown_class
      • 一個測驗用例類 只呼叫一次
  • 模塊
    • setup_module和teardown_module
      • 一個py測驗檔案只執行一次

二、優先級順序

  • 測驗代碼中不建議同時全部使用
  • 先后順序
    • setup執行先后順序
      • module>class>method 類里面的測驗函式
      • module>function 單獨測驗函式的
    • teardown執行先后順序
      • method>class>module 類里面的測驗函式
      • function>moudle 單獨測驗函式的

三、Demo演示

# =============優先級查看代碼=============

def setup_module():
    print('\n>> setup_module  setup_module ...')


def teardown_module():
    print('\n>> teardown_module  teardown_module ...')


def test_one():
    print('\n>>> test_one 111....')


def test_two():
    print('\n>>> test_two 222....')


class TestSetUpMethod():

    def setup_class(self):
        print('\n>> setup_class ...')

    def teardown_class(self):
        print('\n>> teardown_class ...')

    def setup_method(self):
        print('\n>>> setup_method ...')

    def teardown_method(self):
        print('\n>>> teardown_method ...')

    def test_three(self):
        print('\n>>> test_three 333....')

    def test_four(self):
        print('\n>>> test_four 444....')


class TestSetUpMethodTwo():

    def test_three(self):
        print('\n>>> test_three 555....')

    def test_four(self):
        print('\n>>> test_four 666....')

# =================輸出結果==============
setup_module  setup_module ...

>>> test_one 111....
.
>>> test_two 222....
.
>> setup_class ...

>>> setup_method ...

>>> test_three 333....
.
>>> teardown_method ...

>>> setup_method ...

>>> test_four 444....
.
>>> teardown_method ...

>> teardown_class ...

>>> test_three 555....
.
>>> test_four 666....
.
>> teardown_module  teardown_module ...

Pytest-fixture

一 、fixture是什么

  • fixture是pytest特有的功能,它用pytest.fixture標識,以裝飾器形式定義在函式上面,在撰寫測驗函式的時候,可以將此函式名稱做為傳入引數,pytest將會以依賴注入方式,將該函式的回傳值作為測驗函式的傳入引數.

二、 場景舉例

  • 如果測驗類中 5個測驗用例 , 其中 有 3個測驗用例需要登錄, 2個不需要
    • setup_method 可以實作 但是不夠靈活
    • 直接使用fixture就可以實作哪個需要給哪個

三、 使用

@pytest.fixture()
def user_login():
    # 實作用戶登錄
    print('用戶登錄成功')

# 測驗用例:有些要求用戶必須登錄,有些要求可以不登錄訪問
def test_user_orders(user_login):
    print('>>>test_user_orders run >>>')

def test_payment_status(user_login):
    print('>>>test_payment_status run >>>')

# 專案首頁,任何人都可以訪問
def test_index():
    print('>>>test_index run >>>')
# ============不同級別情況下使用fixture的執行次數==========

# function級別共執行3次
# class級別共執行2次
# module級別共執行1次
# session級別共執行1次

# 定義fixture
@pytest.fixture(scope='function')
def user_login():
    # 實作用戶登錄
    print('用戶登錄成功')
# 在類外面使用fixture,在類外面依然可以使用
def test_1(user_login):
    print('>>>test_1 run>>>')

# 在類外面使用fixture,在類里面依然可以使用
class TestLogin(object):
    # 測驗用例:有些要求用戶必須登錄,有些要求可以不登錄訪問
    def test_user_orders(self, user_login):
        print('>>>test_user_orders run >>>')

    def test_payment_status(self, user_login):
        print('>>>test_payment_status run >>>')

四、fixture函式共享

  • 作用
    • 給所有的測驗用例添加可以直接呼叫的功能
  • 實作方式
    • 在測驗檔案目錄下新建 conftest.py 檔案 (檔案名不能修改!!!)
    • 在這個檔案中定義 通用的 可能需要被測驗類呼叫的函式 pytest執行測驗時會自動呼叫
  • demo舉例
# ==========================檔案名:conftest.py======================
import pytest

"""
function:對所有的測驗函式生效,不同的測驗檔案中執行多次;
class:對所有的測驗類和測驗函式生效,不同的測驗檔案中執行多次
module:對所有的測驗類和測驗函式生效,一個測驗檔案,只執行一次

session:對所有的測驗類和測驗函式生效,多個測驗檔案,只執行一次

"""


# 添加功能: 登錄成功輸出資訊
@pytest.fixture(scope='function')
# @pytest.fixture(scope='class')
# @pytest.fixture(scope='module')
# @pytest.fixture(scope='session')
def user_login():
    print('\n用戶登錄成功\n')

# ========================檔案名:fixture_test.py===============
import pytest


# 使用共享檔案中的fixture裝飾的的user_login的功能函式
def test_1(user_login):
    print('\n>>> test_1 run >>>\n')


def test_2():
    print('\n>>> test_2 run >>>\n')


# fixture標記函式共享檔案的使用
@pytest.mark.usefixtures('user_login')
class TestOrders(object):
    """
    fixture標記函式共享檔案的使用:
    1.可以直接傳給測驗類中的指定測驗函式,只對測驗函式生效
    2.也可以直接把測驗類使用fixture進行標記,對該類中的所有測驗函式都生效
    """

    def test_get_orders(self):
        print('\n>>> test_get_orders run >>>\n')

    def test_get_goods(self):
        print('\n>>> test_get_goods run >>>\n')


五、fixture的引數化

  • 三個引數說明

    • scope 作用域:即 function、class、module、session 這四個級別
      • function:即測驗 類外的測驗函式、類中的測驗用例函式 運行多次
      • class:即作用測驗用例類 一個類一次
      • Module:作用整個py模塊 一個模塊一次
      • Sessioon:作用整個一次的測驗包含所有的測驗用例 pytest一次
    • param:List型別,默認None, 接收引數值,對于param里面的每個值,fixture都會去遍歷執行一次.
    • autouse:Bool型別,默認Ture 為true時此session中的所有測驗函式都會呼叫fixture
  • demo

    import pytest
    from _pytest.fixtures import SubRequest
    
    # 1.多個引數串列
    user_list = ['dlireba', 'oyangnanan']
    pwd_list = ['111111', '222222']
    
    
    # 2.多個fixture
    # params引數的用法
    @pytest.fixture(params=user_list)
    def user_name(request):
        return request.param
    
    
    @pytest.fixture(params=pwd_list)
    def pwd_content(request):
        return request.param
    
    # scope引數的用法
    # @pytest.fixture(scope='function')
    @pytest.fixture(scope='class')
    # @pytest.fixture(scope='module')
    # @pytest.fixture(scope='session')
    def pwd_content(request):
        return 'scope測驗'
    
    
    # 3.給測驗函式 多個fixture
    class TestOrders(object):
    
        # 呼叫  fixture裝飾的函式   會自動遍歷匹配   一共會生成4個測驗用例
        def test_get_orders(self, user_name, pwd_content):
            print('\n從fixture傳過來的name資料', user_name)
            print('從fixture傳過來的pwd資料', pwd_content)
            print('>>> test_fixture2 run >>>\n')
    
    # ===   autouse引數  一般情況下不用,影響測驗靈活性======
    # True  一旦執行pytest后的所有的測驗用例將會自動被傳遞hell()函式
    # False  默認關閉此功能
    @pytest.fixture(autouse=True)
    def hello():
        print('\nhello world 2020\n')
    
    

Pytest-mark

一、作用以及常用的5個標記函式

  • 作用

    標記測驗用例,以滿足在某些特定場景下測驗用例的特殊要求實作的功能

  • 6個標記函式

    • pytest.mark.usefixtures 給測驗用例 添加fixture
    • pytest.mark.xfail 標識測驗用例預期失敗
    • pytest.mark.skip 沒有限制條件情況下跳過測驗用例
    • pytest.mark.skipif 有限制條件情況下跳過測驗用例
    • pytest.fixture(params=[]) 直接給fixture函式傳遞引數
    • pytest.mark.parametrize() 直接給測驗用例函式傳遞引數

二、6個標記函式的使用

import pytest


# fixture標記函式共享檔案的使用
@pytest.mark.usefixtures('user_login')
class TestMark():

    def test_one(self):
        print('\n test_one .....')
        assert 1

    """
        pytest.mark.xfail() 
        如果不寫引數  默認預期失敗
        如果有引數   condition reason 必須都寫
    """

    @pytest.mark.xfail(condition=False, reason="測驗 登錄失敗! ")
    def test_two(self):
        print('\n test_two .....')
        assert 0, '測驗失敗了!'

    """
        無條件 跳過
    """

    @pytest.mark.skip()
    def test_three(self):
        print('\n test_three .....')
        assert 1

    """
        有條件 跳過
        pytest.mark.skipif() 
        如果 不寫引數 --默認就跳過
        寫了引數   必須兩個一起寫 condintion  reason
    """

    @pytest.mark.skipif(condition=True, reason='跳過的原因')
    def test_four(self):
        print('\n test_four .....')
        assert 1

    username = "user,pwd"
    values = [('reba', '12345678'), ('oyangnanan', '99999999')]
    """
        key   -argnames     引數型別-string  -- "k1,k2,k3"
        value -argvalues    引數型別-list    -- [v1,v2,v3]
    """

    @pytest.mark.parametrize(username, values)
    def test_five(self, user, pwd):
        print('\n test_five .....')
        print('\n 測驗函式接收外界的引數:', user)
        print('\n 測驗函式接收外界的引數:', pwd)
        print('\n parametrize測驗用例 .....')
        assert 1

    """
        之前的fixture引數傳遞
    """

    @pytest.fixture(params='fixture_param_test')
    def test_six(self, request):
        print('\n test_six .....')
        return request.param

    # 傳遞后使用
    def test_seven(self, test_six):
        print('\n test_seven .....')
        print('\nfixture的param測驗:', test_six)
        assert 1

Pytest的插件

三個常用插件: pytest-html pytest-orderingrun pytest-rerunfailures

安裝:

pip install pytest-html -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pytest-ordering -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pytest-rerunfailures -i https://pypi.tuna.tsinghua.edu.cn/simple

Pytest-html-生成測驗報告

兩種使用方式

  • 終端命令列:pytest 測驗檔案.py --html=存盤路徑/report.html
  • 組態檔中修改:appopts= -s --html=./report.html

Pytest-orderingrun-控制函式執行順序

import pytest
  
# 通過插件,指定測驗函式執行的順序
"""
  正整數:值越小,先執行
  負數:值越小,先執行
  正負數:優先執行正數,最后執行負數,值越小,先執行
  0:優先執行0,然后正數、負數
"""
  
class TestOrdering(object):
    # 默認從上往下執行  !!直接使用標記函式的方式進行呼叫!!
    @pytest.mark.run(order=1)
    def test_login(self):
        print('\n>>>登錄執行>>>\n')
  
    @pytest.mark.run(order=0)
    def test_register(self):
        print('\n>>>注冊執行>>>\n')
  
    @pytest.mark.run(order=2)
    def test_user_info(self):
        print('\n>>>獲取用戶資訊執行>>>\n')

Pytest-rerunfailures-重測驗失敗的用例

**作用 **

  • 就只在某種情況下(網路阻塞、軟體卡頓),測驗用例測驗程序例外測驗失敗,進行自動重新測驗

兩種使用方式

  • 終端命令列:pytest 測驗檔案.py --reruns 重試次數
  • 組態檔中修改:appopts= -s --reruns 重試次數

Yaml

Yaml是什么

一、介紹

? 一種支持所有編程語言的序列化標準,用來存盤資料,類似于json

二、語法規則

  • 大小寫敏感
  • 縮進表示層級關系, 不建議使用tab鍵 縮進空格數量不重要,重要的是同層級對齊即可

三、種資料型別

  • object(物件):

    鍵值對的集合,又稱為映射/hash/字典 —> python中dict

    dilireba: 18
    	oyangnana: kavayi
    		wangyibo: cool
    
  • array(陣列):

    一組按照次序排列的值,又稱序列(sequence)、串列 —> python中list

    dilireba: [18, 18, 18]
    nazha:
    	- 18
    	- 18
    	- 18
    
  • scalars(純量):

    單個的、不可再分的值, 包括 字串、布林值、整數、浮點數、null、日期 —>python中的不可拆分的資料型別

    animal: pets # !!!!!注意冒號后面必須要有一個空格!!!
    	dog: beibei
    # 字串
    value: "hello"
    轉換為python代碼
    {"value":"hello"}
    
    # 布林值
    value1: true
    value2: false
    轉換為python代碼
    {'value1': True, 'value2': False}
    
    # 整數,浮點數
    value1: 12
    value2: 12.102
    # 轉換為python代碼
    {'value1': 12, 'value2': 12.102}
    
    # 空(Null)
    value1: ~ # ~ 表示為空
    轉換為python代碼
    {'value1': None}
    
    # 日期
    value1: 2017-10-11 15:12:12
    轉換為python代碼
    {'languages': {'value1': datetime.datetime(2017, 10, 11, 15, 12, 12)}}
    
  • 錨點的使用

    錨點類似于一個變數,只不過其中只存盤著value供別人呼叫

    data: &ok   # & 是錨點標示符號
        value: 456
    name:
        value1: 123
        <<: *ok # "<<:" 合并到當前位置,"*imp" 參考錨點imp
    
    # 轉換為python代碼  注意字典是無序的  
    # 錨點本身字典也會被pyYAML轉換(下節)
        {'data': {'value': 456}, 'name': {'value': 456, 'value1': 123}}
    

PyYAML決議

一、作用

  • 一個python庫用于對yaml檔案進行決議,決議為字典格式的資料
  • yaml->json->dict

二、安裝

  • pip3 install PyYAML

三、實操

# ========================yaml格式檔案===================


data_one: zhangsan
data_dict: {'user':'A', 'pwd':'123456'}

data_list:
  - a
  - b
  - c

data_list_two: [1,2,3,4]

# 純量  單個變數
str_one: "abcdefg"
bool_data: true
int_data: 100
float_data: 1.2
# 轉換后 呈現格式都是 None
null_data: ~ # ~
null_one: null
null_two: None

datetime_data: 2020-10-13 16:14:24
date_two: 2020-10-13
# 這種時間格式不支持  會轉換成秒數輸出
time_data: 16:14:28
# ===========================測驗代碼=======================
import yaml
from pprint import pprint


def test_parse_yaml_file1():
    f = open('test.yaml', 'r')
    # data = f.read()

    # 1.讀取決議 yaml檔案的資料 Loader默認為空  但是不賦值會有警告
    data = yaml.load(f, Loader=yaml.FullLoader)
    # 字典 格式
    print(type(data))

    # 2.將資料  寫入yaml檔案
    f_write = open('test.yaml', 'a')
    # 新建一個字典資料
    data_dict = {'username': '吳亦凡'}
    # 轉換格式寫入
    yaml.dump(data_dict, f_write, allow_unicode=True)


def test_parse_yaml_file2():
    # 打開
    f = open('test.yaml', 'r')
    # 轉換為字典
    data = yaml.load(f, Loader=yaml.FullLoader)
    # 優化列印出來的資料效果 pprint
    pprint(data)

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/173348.html

標籤:其他

上一篇:Unity游戲開發之UGUI設計——制作一個游戲內置的控制臺界面/作弊選單(詳細流程,附代碼)

下一篇:天天996,試用期4個月,被公司勸退!開發者太糟心了!

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • vue移動端上拉加載

    可能做得過于簡單或者比較low,請各位大佬留情,一起探討技術 ......

    uj5u.com 2020-09-10 04:38:07 more
  • 優美網站首頁,頂部多層導航

    一個個人用的瀏覽器首頁,可以把一下常用的網站放在這里,平常打開會比較方便。 第一步,HTML代碼 <script src=https://www.cnblogs.com/szharf/p/"js/jquery-3.4.1.min.js"></script> <div id="navigate"> <ul> <li class="labels labels_1"> ......

    uj5u.com 2020-09-10 04:38:47 more
  • 頁面為要加<!DOCTYPE html>

    最近因為寫一個js函式,需要用到$(window).height(); 由于手寫demo的時候,過于自信,其實對前端方面的認識也不夠體系,用文本檔案直接敲出來的html代碼,第一行沒有加上<!DOCTYPE html> 導致了$(window).height();的結果直接是整個document的高 ......

    uj5u.com 2020-09-10 04:38:52 more
  • WordPress網站程式手動升級要做好資料備份

    WordPress博客網站程式在進行升級前,必須要做好網站資料的備份,這個問題良家佐言是遇見過的;在剛開始接觸WordPress博客程式的時候,因為升級問題和博客網站的修改的一些嘗試,良家佐言是吃盡了苦頭。因為購買的是西部數碼的空間和域名,每當佐言把自己的WordPress博客網站搞到一塌糊涂的時候 ......

    uj5u.com 2020-09-10 04:39:30 more
  • WordPress程式不能升級為5.4.2版本的原因

    WordPress是一款個人博客系統,受到英文博客愛好者和中文博客愛好者的追捧,并逐步演化成一款內容管理系統軟體;它是使用PHP語言和MySQL資料庫開發的,用戶可以在支持PHP和MySQL資料庫的服務器上使用自己的博客。每一次WordPress程式的更新,就會牽動無數WordPress愛好者的心, ......

    uj5u.com 2020-09-10 04:39:49 more
  • 使用CSS3的偽元素進行首字母下沉和首行改變樣式

    網頁中常見的一種效果,首字改變樣式或者首行改變樣式,效果如下圖。 代碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ......

    uj5u.com 2020-09-10 04:40:09 more
  • 關于a標簽的講解

    什么是a標簽? <a> 標簽定義超鏈接,用于從一個頁面鏈接到另一個頁面。 <a> 元素最重要的屬性是 href 屬性,它指定鏈接的目標。 a標簽的語法格式:<a href=https://www.cnblogs.com/summerxbc/p/"指定要跳轉的目標界面的鏈接">需要展示給用戶看見的內容</a> a標簽 在所有瀏覽器中,鏈接的默認外觀如下: 未被訪問的鏈接帶 ......

    uj5u.com 2020-09-10 04:40:11 more
  • 前端輪播圖

    在需要輪播的頁面是引入swiper.min.js和swiper.min.css swiper.min.js地址: 鏈接:https://pan.baidu.com/s/15Uh516YHa4CV3X-RyjEIWw 提取碼:4aks swiper.min.css地址 鏈接:https://pan.b ......

    uj5u.com 2020-09-10 04:40:13 more
  • 如何設定html中的背景圖片(全屏顯示,且不拉伸)

    1 <style>2 body{background-image:url(https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture); 3 background-size:cover;background ......

    uj5u.com 2020-09-10 04:40:16 more
  • Java學習——HTML詳解(上)

    HTML詳解 初識HTML Hyper Text Markup Language(超文本標記語言) 1 <!--DOCTYPE:告訴瀏覽器我們要使用什么規范--> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <!--meta 描述性的標簽,描述一些 ......

    uj5u.com 2020-09-10 04:40:33 more
最新发布
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 07:59:23 more
  • 生產事故-走近科學之消失的JWT

    入職多年,面對生產環境,盡管都是小心翼翼,慎之又慎,還是難免捅出簍子。輕則滿頭大汗,面紅耳赤。重則系統停擺,損失資金。每一個生產事故的背后,都是寶貴的經驗和教訓,都是專案成員的血淚史。為了更好地防范和遏制今后的各類事故,特開此專題,長期更新和記錄大大小小的各類事故。有些是親身經歷,有些是經人耳傳口授 ......

    uj5u.com 2023-04-18 07:55:04 more
  • 記錄--Canvas實作打飛字游戲

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 打開游戲界面,看到一個畫面簡潔、卻又富有挑戰性的游戲。螢屏上,有一個白色的矩形框,里面不斷下落著各種單詞,而我需要迅速地輸入這些單詞。如果我輸入的單詞與螢屏上的單詞匹配,那么我就可以獲得得分;如果我輸入的單詞錯誤或者時間過長,那么我就會輸 ......

    uj5u.com 2023-04-04 08:35:30 more
  • 了解 HTTP 看這一篇就夠

    在學習網路之前,了解它的歷史能夠幫助我們明白為何它會發展為如今這個樣子,引發探究網路的興趣。下面的這張圖片就展示了“互聯網”誕生至今的發展歷程。 ......

    uj5u.com 2023-03-16 11:00:15 more
  • 藍牙-低功耗中心設備

    //11.開啟藍牙配接器 openBluetoothAdapter //21.開始搜索藍牙設備 startBluetoothDevicesDiscovery //31.開啟監聽搜索藍牙設備 onBluetoothDeviceFound //30.停止監聽搜索藍牙設備 offBluetoothDevi ......

    uj5u.com 2023-03-15 09:06:45 more
  • canvas畫板(滑鼠和觸摸)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canves</title> <style> #canvas { cursor:url(../images/pen.png),crosshair; } #canvasdiv{ bo ......

    uj5u.com 2023-02-15 08:56:31 more
  • 手機端H5 實作自定義拍照界面

    手機端 H5 實作自定義拍照界面也可以使用 MediaDevices API 和 <video> 標簽來實作,和在桌面端做法基本一致。 首先,使用 MediaDevices.getUserMedia() 方法獲取攝像頭媒體流,并將其傳遞給 <video> 標簽進行渲染。 接著,使用 HTML 的 < ......

    uj5u.com 2023-01-12 07:58:22 more
  • 記錄--短視頻滑動播放在 H5 下的實作

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 短視頻已經無數不在了,但是主體還是使用 app 來承載的。本文講述 H5 如何實作 app 的視頻滑動體驗。 無聲勝有聲,一圖頂百辯,且看下圖: 網址鏈接(需在微信或者手Q中瀏覽) 從上圖可以看到,我們主要實作的功能也是本文要講解的有: ......

    uj5u.com 2023-01-04 07:29:05 more
  • 一文讀懂 HTTP/1 HTTP/2 HTTP/3

    從 1989 年萬維網(www)誕生,HTTP(HyperText Transfer Protocol)經歷了眾多版本迭代,WebSocket 也在期間萌芽。1991 年 HTTP0.9 被發明。1996 年出現了 HTTP1.0。2015 年 HTTP2 正式發布。2020 年 HTTP3 或能正... ......

    uj5u.com 2022-12-24 06:56:02 more
  • 【HTML基礎篇002】HTML之form表單超詳解

    ??一、form表單是什么

    ??二、form表單的屬性

    ??三、input中的各種Type屬性值

    ??四、標簽 ......

    uj5u.com 2022-12-18 07:17:06 more