如果你還想從頭學起Pytest,可以看看這個系列的文章哦!
https://www.cnblogs.com/poloyy/category/1690628.html
pytest-xdist分布式測試的原理
前言
- xdist的分布式類似於一主多從的結構,master機負責下發命令,控制slave機;slave機根據master機的命令執行特定測試任務
- 在xdist中,主是master,從是workers
大致原理
- xdist會產生一個或多個workers,workers都通過master來控制
- 每個worker負責執行完整的測試用例集,然后按照master的要求運行測試,而master機不執行測試任務
pytest-xdist分布式測試的流程
第一步:創建worker
- master會在總測試會話(test session)開始前產生一個或多個worker
- master和worker之間是通過execnet和網關來通信的
- 實際編譯執行測試代碼的worker可能是本地機器也可能是遠程機器
第二步:收集測試項用例
- 每個worker類似一個迷你型的pytest執行器
- worker會執行一個完整的test collection過程【收集所有測試用例的過程】
- 然后把測試用例的ids返回給master
- master是不會執行任何測試用例集的
注意
所以為什么上面通過分布式測試的結果截圖是沒有輸出用例的print內容,因為主機並不執行測試用例,pycharm相當於一個master
第三步:master檢測workers收集到的測試用例集
- master接收到所有worker收集的測試用例集之后,master會進行一些完整性檢查,以確保所有worker都收集到一樣的測試用例集(包括順序)
- 如果檢查通過,會將測試用例的ids列表轉換成簡單的索引列表,每個索引對應一個測試用例的在原來測試集中的位置
- 這個方案可行的原因是:所有的節點都保存着相同的測試用例集
- 並且使用這種方式可以節省帶寬,因為master只需要告知workers需要執行的測試用例對應的索引,而不用告知完整的測試用例信息
第四步:測試用例分發
--dist-mode選項
each:master將完整的測試索引列表分發到每個worker
load:master將大約25%的測試用例以輪詢的方式分發到各個worker,剩余的測試用例則會等待workers執行完測試用例以后再分發
注意
可以使用 pytest_xdist_make_scheduler 這個hook來實現自定義測試分發邏輯。
第五步:測試用例的執行
- workers 重寫了 pytest_runtestloop :pytest的默認實現是循環執行所有在test session這個對象里面收集到的測試用例
- 但是在xdist里, workers實際上是等待master為其發送需要執行的測試用例
- 當worker收到測試任務, 就順序執行 pytest_runtest_protocol
- 值得注意的一個細節是:workers 必須始終保持至少一個測試用例在的任務隊列里, 以兼容 pytest_runtest_protocol(item, nextitem) hook的參數要求,為了將 nextitem傳給hook
- worker會在執行最后一個測試項前等待master的更多指令
- 如果它收到了更多測試項, 那么就可以安全的執行 pytest_runtest_protocol , 因為這時nextitem參數已經可以確定
- 如果它收到一個 "shutdown"信號, 那么就將 nextitem 參數設為 None, 然后執行 pytest_runtest_protocol
第六步:測試用例再分發(--dist-mode=load)
- 當workers開始/結束執行時,會把測試結果返回給master,這樣其他pytest hook比如: pytest_runtest_protocol 和 pytest_runtest_protocol 就可以正常執行
- master在worker執行完一個測試后,基於測試執行時長以及每個work剩余測試用例綜合決定是否向這個worker發送更多的測試用例
第七步:測試結束
- 當master沒有更多執行測試任務時,它會發送一個“shutdown”信號給所有worker
- 當worker將剩余測試用例執行完后退出進程
- master等待所有worker全部退出
- 然此時仍需要處理諸如 pytest_runtest_logreport 等事件