Python的學(xué)習(xí)日志
背景:5月底,主動(dòng)報(bào)名了公司的某IOT項(xiàng)目的出差任務(wù)。by the way,其實(shí)主要報(bào)名原因是考慮到這個(gè)項(xiàng)目會(huì)有自動(dòng)化的測試需求,說是出差到北京后主要會(huì)負(fù)責(zé)自動(dòng)化的內(nèi)容。
考慮到后面職業(yè)未來,功能測試的前景,我覺得自動(dòng)化前景會(huì)稍微好一些。(當(dāng)然這里涉及到業(yè)務(wù)線與技術(shù)線,二者缺一不可,但技術(shù)的機(jī)會(huì)先出現(xiàn)在我面前我也就只能先把握住我能把握住的機(jī)會(huì)了)
學(xué)習(xí)背景:1、有一定的語言基礎(chǔ)(C,C++,C#,JAVA,Python)。當(dāng)然,這里的語言基礎(chǔ)主要是指基礎(chǔ)語法與一些基本原理,像JAVA的主要框架(SpringBoot等等)其實(shí)并沒有學(xué)習(xí)到,主要還是本科學(xué)校對于計(jì)科這門專業(yè)的學(xué)習(xí)的定位原因吧(這里就不深入討論了)。2、數(shù)據(jù)結(jié)構(gòu)、計(jì)組、計(jì)網(wǎng)的一些理論知識(shí)。(本科+考研時(shí)的學(xué)習(xí)內(nèi)容)
公司給了2個(gè)星期左右的時(shí)間讓我重新?lián)炱餚ython吧。主要也是項(xiàng)目空閑下來了,新項(xiàng)目又沒有開始,所以剛好給了我一個(gè)緩沖期(??真好)所以這個(gè)日志一次性更新了很多內(nèi)容,主要也是我在公司學(xué)習(xí)時(shí)的記錄。并用GPT幫我整理了一份markdown格式的
如有遺漏或部分理解的錯(cuò)誤,請指正\或發(fā)郵件到:603992850@qq.com,在此拜謝
模塊1:面向?qū)ο蟾呒壧匦浴惓Ec日志、生成器與裝飾器
1.1 __slots__ — 限定實(shí)例屬性,優(yōu)化內(nèi)存
__slots__是類變量,用于規(guī)定類實(shí)例允許擁有的屬性集合。這樣實(shí)例不能隨意添加未在__slots__中聲明的屬性。- 作用:
- 限制實(shí)例屬性,避免意外新增多余屬性
- 減少內(nèi)存占用:使用
__slots__后實(shí)例不再使用字典存儲(chǔ)屬性,減少約30%的內(nèi)存消耗。
- 細(xì)節(jié)與技巧:
- 導(dǎo)入
types.MethodType,可以給實(shí)例動(dòng)態(tài)綁定類中不存在的方法。 - 子類繼承父類的
__slots__,但默認(rèn)子類會(huì)獲得__dict__,除非子類自己重新聲明__slots__。 - 類實(shí)例允許的屬性是自身的
__slots__+ 父類的__slots__的合集。 __slots__不能限制類本身添加屬性,類屬性依然可以自由添加。
- 導(dǎo)入
1.2 @property 裝飾器 — 方法變屬性,控制訪問
-
@property是Python內(nèi)置裝飾器,作用是讓方法表現(xiàn)得像訪問屬性一樣。 -
作用:
- 把類中的方法變?yōu)椤爸蛔x屬性”,避免外部直接調(diào)用函數(shù)的括號(hào)形式。
- 只定義
@property,不定義對應(yīng)的 setter,會(huì)讓屬性變?yōu)橹蛔x。
-
注意事項(xiàng):
-
如果方法名和屬性名相同,且方法體里訪問了自身屬性(例如
return self.x),會(huì)導(dǎo)致無限遞歸。
例如:@property def x(self): return self.x # 無限遞歸! -
訪問
@property屬性的速度會(huì)比直接訪問屬性慢一些,因?yàn)槭钦{(diào)用函數(shù)。
-
1.3 多重繼承
-
Python支持多重繼承,子類可以繼承多個(gè)父類的功能。相比Java單繼承,Python的多重繼承更靈活。
-
約定俗成的寫法:
-
主父類不寫MixIn
-
額外功能用MixIn類提供
-
例如:
class Bat(Mammal, FlyableMixIn): pass
-
-
MixIn類設(shè)計(jì)原則:
- 只提供特定功能,不單獨(dú)實(shí)例化
- 用于組合拓展類的功能,不構(gòu)成復(fù)雜繼承鏈
1.4 錯(cuò)誤處理機(jī)制(try-except-else-finally)
-
基本結(jié)構(gòu):
try: # 可能拋出異常的代碼 except SomeError as e: # 捕獲并處理SomeError else: # 無異常時(shí)執(zhí)行 finally: # 無論異常與否都會(huì)執(zhí)行 -
細(xì)節(jié)說明:
raise語句:- 不帶參數(shù)時(shí),會(huì)重新拋出當(dāng)前異常。
- 可以用來在
except中將一種錯(cuò)誤轉(zhuǎn)化成另一種錯(cuò)誤拋出。
1.5 Logging模塊 — 記錄日志的五個(gè)重要級別及配置
-
五個(gè)級別:
- DEBUG(調(diào)試細(xì)節(jié))
- INFO(一般信息)
- WARNING(警告)
- ERROR(錯(cuò)誤)
- CRITICAL(嚴(yán)重錯(cuò)誤)
-
設(shè)置日志級別,只記錄指定級別及以上的日志:
logging.basicConfig(level=logging.INFO) -
輸出日志到文件,格式示例:
logging.basicConfig( filename='app.log', level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' )- 其中格式字符串由 logging 自動(dòng)填充:時(shí)間、日志器名稱、日志級別、日志內(nèi)容。
1.6 斷言(assert)
- 斷言是程序中的自檢機(jī)制,作用類似于
print但更專業(yè)。 - 用于檢查程序中某些條件是否為真,若斷言失敗,程序會(huì)拋出
AssertionError。 - 常用于單元測試或調(diào)試階段,快速定位錯(cuò)誤。
1.7 yield — 生成器函數(shù)核心
- 在函數(shù)中使用
yield關(guān)鍵字,函數(shù)不再是普通函數(shù),而是生成器函數(shù)。 - 生成器函數(shù)返回一個(gè)生成器對象,可以逐個(gè)“產(chǎn)出”值,而不是一次性返回所有結(jié)果。
- 優(yōu)勢:節(jié)省內(nèi)存,支持惰性計(jì)算。
1.8 functools.wraps — 保留裝飾器函數(shù)元信息
-
在自定義裝飾器中,使用
@wraps(func)可讓裝飾后的函數(shù)保持原函數(shù)的名字、文檔字符串等元信息。 -
有利于調(diào)試和文檔生成。
-
示例:
from functools import wraps def my_decorator(func): @wraps(func) def wrapper(*args, **kwargs): print(f"調(diào)用函數(shù): {func.__name__}") return func(*args, **kwargs) return wrapper
1.9 方法重寫
- Python支持類中方法的重寫,類似Java。
- 子類可以拓展或修改父類方法的功能,實(shí)現(xiàn)多態(tài)。
1.10 logging中Logger的使用
- 通過
logging.getLogger("logger名稱")獲取日志對象。 - 常用Handler:
- StreamHandler — 控制臺(tái)輸出
- FileHandler — 日志文件輸出
1.11 pdb 調(diào)試工具
- Python內(nèi)置的單步調(diào)試器。
- 可以在代碼中插入斷點(diǎn),單步調(diào)試程序。
- 現(xiàn)代IDE通常有自帶更友好的調(diào)試功能,更常用。
模塊2:Python測試框架與單元測試、pytest深度解析、自動(dòng)化測試工具
2.1 單元測試基礎(chǔ) — unittest模塊
-
Python內(nèi)置的單元測試框架,模擬Java的JUnit。
-
主要類:
unittest.TestCase:測試用例基類setUp():每個(gè)測試方法執(zhí)行前調(diào)用tearDown():每個(gè)測試方法執(zhí)行后調(diào)用
-
結(jié)構(gòu)示例:
import unittest class MyTest(unittest.TestCase): def setUp(self): # 測試準(zhǔn)備工作 pass def test_func(self): self.assertEqual(1 + 1, 2) def tearDown(self): # 測試清理工作 pass if __name__ == "__main__": unittest.main() -
常用斷言方法:
assertEqual,assertTrue,assertFalse,assertRaises等。
2.2 pytest入門與運(yùn)行方式
-
輕量且強(qiáng)大的測試框架,兼容unittest。
-
優(yōu)點(diǎn):
- 用例函數(shù)命名無需繼承類,函數(shù)名以
test_開頭即可 - 支持參數(shù)化、夾具,豐富的插件生態(tài)
- 友好的斷言機(jī)制,失敗時(shí)自動(dòng)顯示表達(dá)式詳細(xì)信息
- 用例函數(shù)命名無需繼承類,函數(shù)名以
-
運(yùn)行命令:
pytest test_sample.py -
可以直接運(yùn)行含有
test_前綴的函數(shù),自動(dòng)發(fā)現(xiàn)并執(zhí)行。
2.3 pytest斷言機(jī)制詳解
-
pytest使用Python的
assert語句替代傳統(tǒng)斷言方法。 -
失敗時(shí),pytest自動(dòng)解析表達(dá)式,展示詳細(xì)失敗原因。
-
例如:
def test_example(): a = 1 b = 2 assert a + b == 4 # 斷言失敗,pytest自動(dòng)打印詳細(xì)表達(dá)式和變量值
2.4 pytest夾具(Fixture)
-
夾具是pytest的核心特性,用于測試前準(zhǔn)備和后清理工作。
-
通過裝飾器
@pytest.fixture定義。 -
作用域可以設(shè)置為函數(shù)級、模塊級、會(huì)話級等,復(fù)用性強(qiáng)。
-
示例:
import pytest @pytest.fixture def setup_data(): data = {"key": "value"} yield data # 測試后清理代碼 def test_use_data(setup_data): assert setup_data["key"] == "value" -
yield前是準(zhǔn)備過程,yield后是清理過程。
2.5 pytest參數(shù)化
-
通過
@pytest.mark.parametrize裝飾器,輕松實(shí)現(xiàn)同一測試用例多組數(shù)據(jù)測試。 -
示例:
@pytest.mark.parametrize("input, expected", [ (1, 2), (3, 4), (5, 6) ]) def test_add_one(input, expected): assert input + 1 == expected
2.6 pytest跳過與預(yù)期失敗標(biāo)記
-
標(biāo)記用例跳過:
import pytest @pytest.mark.skip(reason="跳過該測試") def test_skip(): pass -
標(biāo)記預(yù)期失敗:
@pytest.mark.xfail(reason="已知BUG,暫時(shí)失敗") def test_xfail(): assert False
2.7 pytest命令行常用參數(shù)
-
-v:詳細(xì)模式,顯示更多測試信息 -
-k:根據(jù)表達(dá)式過濾測試用例 -
-m:根據(jù)標(biāo)記過濾用例 -
--maxfail=N:失敗達(dá)到N個(gè)停止執(zhí)行 -
--tb=short/long/no:控制traceback打印風(fēng)格 -
示例:
pytest -v -k "test_add" -m "smoke"
2.8 pytest插件系統(tǒng)
-
pytest生態(tài)豐富,插件眾多。常用插件包括:
pytest-html:生成HTML格式測試報(bào)告pytest-xdist:分布式并行執(zhí)行測試用例pytest-cov:覆蓋率統(tǒng)計(jì)
-
安裝示例:
pip install pytest-html pytest-xdist pytest-cov
2.9 Allure報(bào)告集成
-
Allure是美觀的測試報(bào)告工具,支持pytest。
-
集成步驟:
- 安裝allure命令行工具(需系統(tǒng)環(huán)境支持)
- 安裝pytest-allure-adaptor插件或pytest-allure-plugin(具體版本視環(huán)境而定)
- 在測試代碼中使用Allure裝飾器(例如
@allure.feature、@allure.story等)標(biāo)記測試用例。 - 運(yùn)行測試時(shí)生成Allure結(jié)果數(shù)據(jù)目錄,之后通過命令行生成報(bào)告。
-
示例:
pytest --alluredir=./allure-results allure serve ./allure-results
2.10 測試框架封裝與自動(dòng)化測試工具開發(fā)
2.10.1 推薦目錄結(jié)構(gòu)
project_root/
├── tests/ # 測試用例目錄
│ ├── test_login.py
│ ├── test_profile.py
│ └── conftest.py # pytest夾具和全局配置
├── pages/ # 頁面對象或接口封裝
│ ├── login_page.py
│ └── profile_page.py
├── utils/ # 工具類
│ ├── http_client.py # 封裝請求方法
│ └── logger.py # 日志封裝
├── data/ # 測試數(shù)據(jù),yaml/json等
│ └── test_data.yaml
├── reports/ # 測試報(bào)告目錄
├── requirements.txt # 依賴包管理
└── pytest.ini # pytest配置文件
2.10.2 核心代碼示例
1) 封裝HTTP請求(utils/http_client.py)
import requests
class HttpClient:
def __init__(self, base_url):
self.base_url = base_url
def get(self, path, params=None, headers=None):
url = self.base_url + path
response = requests.get(url, params=params, headers=headers)
return response
def post(self, path, json=None, headers=None):
url = self.base_url + path
response = requests.post(url, json=json, headers=headers)
return response
2) 日志封裝(utils/logger.py)
import logging
def get_logger(name):
logger = logging.getLogger(name)
if not logger.hasHandlers():
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
return logger
3) pytest夾具示例(tests/conftest.py)
import pytest
from utils.http_client import HttpClient
@pytest.fixture(scope="session")
def base_url():
return "https://api.example.com"
@pytest.fixture(scope="session")
def client(base_url):
return HttpClient(base_url)
4) 測試用例示例(tests/test_login.py)
import pytest
def test_login_success(client):
response = client.post("/login", json={"username": "user1", "password": "pass123"})
assert response.status_code == 200
assert response.json().get("token") is not None
@pytest.mark.parametrize("username,password", [
("user1", ""),
("", "pass123"),
("", "")
])
def test_login_fail(client, username, password):
response = client.post("/login", json={"username": username, "password": password})
assert response.status_code == 400
2.10.3 配置pytest.ini示例
[pytest]
addopts = -v --maxfail=3 --tb=short
testpaths = tests
python_files = test_*.py
markers =
smoke: 快速冒煙測試
regression: 回歸測試
2.11 接口測試用例設(shè)計(jì)
- 測試步驟:
- 明確接口功能與參數(shù)
- 編寫接口請求代碼(get/post等)
- 編寫斷言驗(yàn)證響應(yīng)狀態(tài)碼、響應(yīng)體內(nèi)容
- 覆蓋正常用例與異常用例(邊界值、無效輸入等)
- 使用pytest參數(shù)化,提高用例覆蓋率
- 可結(jié)合Allure進(jìn)行接口測試報(bào)告展示。
2.12 自動(dòng)化測試中常用工具和庫
requests:HTTP請求,接口測試必備pytest:測試執(zhí)行與管理allure-pytest:報(bào)告美化jsonschema:接口響應(yīng)數(shù)據(jù)格式校驗(yàn)faker:模擬生成測試數(shù)據(jù)selenium/Appium:UI自動(dòng)化測試(非本模塊重點(diǎn))
模塊3:Python進(jìn)階應(yīng)用與測試開發(fā)實(shí)戰(zhàn)技巧
3.1 Python文件操作基礎(chǔ)與技巧
3.1.1 打開與關(guān)閉文件
python復(fù)制編輯f = open("data.txt", "r", encoding="utf-8")
content = f.read()
f.close()
推薦使用 with 語法,自動(dòng)關(guān)閉文件:
python復(fù)制編輯with open("data.txt", "r", encoding="utf-8") as f:
content = f.read()
3.1.2 常用文件讀寫方法
read():讀取整個(gè)文件內(nèi)容readline():讀取一行readlines():按行讀取為列表write(str):寫入字符串writelines(list):寫入多個(gè)字符串
3.2 Python序列化:json 與 pickle
3.2.1 JSON模塊(常用于接口數(shù)據(jù))
python復(fù)制編輯import json
data = {"name": "Calvin", "age": 25}
json_str = json.dumps(data) # 序列化為字符串
with open("user.json", "w") as f:
json.dump(data, f) # 寫入文件
with open("user.json", "r") as f:
user = json.load(f) # 反序列化
3.2.2 Pickle模塊(支持Python對象)
python復(fù)制編輯import pickle
obj = {"name": "test", "scores": [90, 80]}
with open("data.pkl", "wb") as f:
pickle.dump(obj, f)
with open("data.pkl", "rb") as f:
result = pickle.load(f)
3.3 正則表達(dá)式實(shí)戰(zhàn)技巧
3.3.1 常見模式符號(hào)
| 表達(dá)式 | 含義 |
|---|---|
. |
任意字符(換行除外) |
\d |
數(shù)字,等價(jià)于 [0-9] |
\w |
單詞字符 [A-Za-z0-9_] |
* |
0個(gè)或多個(gè) |
+ |
1個(gè)或多個(gè) |
? |
0個(gè)或1個(gè) |
| ` | ` |
^ |
開頭匹配 |
$ |
結(jié)尾匹配 |
3.3.2 常用方法
python復(fù)制編輯import re
text = "My phone number is 18812345678"
pattern = r"\d{11}"
result = re.search(pattern, text)
print(result.group()) # 輸出 18812345678
re.match():從頭匹配re.search():搜索首個(gè)匹配re.findall():返回所有匹配項(xiàng)re.sub(pattern, repl, string):替換匹配字符串
3.4 多線程與多進(jìn)程編程
3.4.1 threading模塊
python復(fù)制編輯import threading
def run():
print("Thread running")
t = threading.Thread(target=run)
t.start()
t.join()
threading.Thread()創(chuàng)建線程start()啟動(dòng)線程join()等待線程結(jié)束
3.4.2 multiprocessing模塊
python復(fù)制編輯from multiprocessing import Process
def task():
print("Process task")
p = Process(target=task)
p.start()
p.join()
- 使用多進(jìn)程避免Python GIL(全局解釋器鎖)帶來的性能瓶頸。
3.5 網(wǎng)絡(luò)編程基礎(chǔ)
3.5.1 socket模塊實(shí)現(xiàn)通信
python復(fù)制編輯import socket
s = socket.socket()
s.connect(('www.example.com', 80))
s.send(b"GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n")
data = s.recv(1024)
print(data.decode())
s.close()
- 常用于自定義TCP/UDP協(xié)議通信測試
- 適合理解自動(dòng)化測試中設(shè)備網(wǎng)絡(luò)通信機(jī)制
3.6 subprocess子進(jìn)程管理(自動(dòng)化測試常用)
3.6.1 常用方法
python復(fù)制編輯import subprocess
# 獲取命令輸出
output = subprocess.check_output(["adb", "devices"], encoding="utf-8")
print(output)
# 實(shí)時(shí)打印日志(適用于 Monkey 掛測場景)
p = subprocess.Popen("adb logcat", shell=True)
check_output():獲取輸出結(jié)果run():執(zhí)行命令并返回結(jié)果對象Popen():適合長時(shí)間運(yùn)行的任務(wù),支持實(shí)時(shí)通信
3.7 logging模塊:日志輸出規(guī)范
python復(fù)制編輯import logging
logging.basicConfig(
filename="app.log",
level=logging.DEBUG,
format="%(asctime)s - %(levelname)s - %(message)s"
)
logging.info("This is info")
logging.error("This is error")
DEBUG<INFO<WARNING<ERROR<CRITICAL- 可將日志寫入文件或控制臺(tái),方便調(diào)試和記錄測試結(jié)果
3.8 Python項(xiàng)目打包與部署
3.8.1 使用 PyInstaller 打包 GUI 工具
bash
復(fù)制編輯
pyinstaller -F -w your_app.py
-F:打包為單個(gè)文件-w:窗口應(yīng)用,不顯示控制臺(tái)
3.8.2 示例:Monkey掛測工具打包
打包你寫的“Monkey多設(shè)備掛測工具”,可用于交付和面試作品展示。
3.9 實(shí)戰(zhàn)建議與面試準(zhǔn)備技巧
- 面試項(xiàng)目準(zhǔn)備建議:
- 展示清晰的項(xiàng)目目錄結(jié)構(gòu)
- 代碼應(yīng)模塊化、具備注釋、夾具、參數(shù)化等
- 具備日志收集、測試報(bào)告生成、異常處理機(jī)制
- 能打包為可交付工具,如
.exe或.sh
- 面試重點(diǎn)模塊:
- pytest 的 fixture/parametrize/xfail 等特性
- requests/Allure/日志/目錄結(jié)構(gòu) 等是否規(guī)范
- Python 基礎(chǔ)是否扎實(shí)(文件操作、異常處理、并發(fā))
- 能否獨(dú)立封裝框架,理解設(shè)計(jì)思路

浙公網(wǎng)安備 33010602011771號(hào)