一、python安裝
1.windows(server):
雙擊python-3.6.7-amd64.exe執行安裝流程,使用默認安裝方式即可。
安裝完成后查看是否安裝成功:
C:\Users\Administrator>python --version
'python' is not recognized as an internal or external command,
operable program or batch file.
如果出現不識別python的情況,需要將python的安裝路徑添加到環境變量,computer->properties->enviroment variables,
找到Path變量,將python的安裝路徑和安裝路徑下的Scripts目錄加在后面。
比如:
C:\Users\Administrator\AppData\Local\Programs\Python\Python36;C:\Users\Administrator\AppData\Local\Programs\Python\Python36\Scripts
重新打開cmd窗口,再次查看python版本,
C:\Users\Administrator>python --version
Python 3.6.7
安裝成功
2.linux:
# tar -xJf Python-3.6.7.tar.xz
# cd Python-3.6.7/
# ./configure --prefix=/usr/local/python --enable-shared CFLAGS=-fPIC
# make
# make install
安裝完成后,查看python版本還是2.7, # python --version
python 2.7.13
這是因為在/usr/bin下的python是一個指向python2.7的軟連接,需要手工調整下:
# ls -l /usr/bin/python
lrwxrwxrwx 1 root root 9 Dec 6 2017 /usr/bin/python -> python2.7
# rm /usr/bin/python
# ln -s /usr/local/python/bin/python3.6 /usr/bin/python
后續如果用到其他的軟件必須使用2.7的情況時可以用同樣的方法切回來
這時候再check下python的版本情況:
# python --version
python: error while loading shared libraries: libpython3.6m.so.1.0: cannot open shared object file: No such file or directory
提示找不到libpython3.6m.so.1.0,那是因為之前編譯出來的so文件安裝在了/usr/local/python/lib,需要將這個路徑加到系統的so搜索路徑中:
將路徑增加到/etc/ld.so.conf文件中
# cat /etc/ld.so.conf
/usr/local/lib64
/usr/local/lib
/usr/local/python/lib/
include /etc/ld.so.conf.d/*.conf
# ldconfig
再次check安裝已經完成:
# python --version
Python 3.6.7
備注:
Python安裝過程中會依賴zlib,部分linux版本沒有zlib需要自行安裝,安裝方法如下:
cd zlib-1.2.8/
./configure
Make && make install
二、pip安裝
1.windows(server):
在C:\Users\用戶名\pip 目錄(如果沒有就新建一個)下添加pip.ini 文件,然后編輯其內容如下(配置這個的目的是使用pip install下載安裝服務器上的支撐庫包,如果使用pip自帶庫默認設置即可):
[global]
trusted-host=pip ftp服務器地址
index-url=http://pip ftp服務器地址/simple/
配置完成打開cmd,使用pip install檢查pip是否可用,C:\Users\Administrator>pip install setuptools-scm
pip安裝完成后安裝pycharm ide開發工具,從pycharm官網或者附件中下載pycharm安裝包,雙擊安裝,安裝過程中需要注意的步驟如下:
注意:
(1)安裝過程勾選add lanchers dir to the PATH
(2)安裝完成后就可以使用了,首先創建一個工程,可以將工程創建在已下載的測試腳本目錄中,新建一個工程后,左上角file->Setting->Tools->Python Integrated Tools-> Default test runner->選擇pytest
2.linux:
pip源碼傳到linux。
# cd pip-18.1
# python setup.py install
# ln -s /usr/local/python/bin/pip /usr/local/bin/pip
# pip --version
pip 18.1 from /usr/local/python/lib/python3.6/site-packages/pip-18.1-py3.6.egg/pip (python 3.6)
安裝完成后需要配置下pip服務器(配置這個的目的是使用pip install下載安裝服務器上的支撐庫包,如果使用pip自帶庫默認設置即可):
編輯~/.pip/目錄下的pip.conf文件(如果沒有則創建該文件~/.pip/pip.conf),然后編輯其內容如下
[global]
trusted-host=pip ftp服務器地址
index-url=http://pip ftp服務器地址/simple/
三、安裝pytest依賴庫
pip install pytest
pip install pytest-html
pip install paramiko
pip install rpyc
pip install request
四、使用pytest
1.配置文件
pytest.ini是pytest的主配置文件,可以改變pytest的默認行為,按指定的方式去運行。Pytest.ini的基本格式:
# 保存為pytest.ini文件
[pytest]
addopts = -rsxX
pytest.ini可以放在測試腳本的目錄中或者通過pytest調用時的命令行參數指定:
pytest -c "E:\Desktop\pytest_local.ini"
不推薦使用命令行參數指定的方式,因為使用-c參數后,原來在測試腳本根目錄中的pytest.ini就默認不使能了,pytest就會使用當前文件夾作為rootdir,破壞了一般意義上我們測試腳本的根目錄是pytest.ini所在目錄的固定觀念。當然,我們可以通過制定命令行參數---rootdir來指定運行根目錄:
testcase\dir_level1\dir_level2>pytest -c "E:\Desktop\pytest_local.ini" --rootdir="E:\Desktop\Sublime Text Build_x64\test_ini"
pytest確定rootdir的方法見手冊:
https://docs.pytest.org/en/latest/customize.html#initialization-determining-rootdir-and-inifile
2.配置項
本節會介紹我們常用的配置項,對於其他的配置項,請在官方手冊中查詢。
adopts
addopts參數可以更改默認命令行選項,等同於我們在cmd輸入指令去執行用例的時候加的參數,比如指定測試床信息和生成的日志文件目錄:
[pytest]
addopts = --testbed="E:\Desktop\topology_template.yaml" --reportpath="E:\Desktop"
--testbed
用於指定測試床的命令行參數,可以寫入addopts中或者在調用的時候手動輸出,該參數必選。
--reportpath
用於指定生成日志文件的根目錄,如果不選,日志文件會默認選擇pytest的rootdir作為日志的根目錄
python_functions
匹配測試用例編號,用例編號一般都是有固定開頭的,比如以TestCase_開頭,因此配置為TestCase_
python_files
匹配測試腳本文件名,TestCase的腳本名都是TestCase_開頭的,因此配置為TestCase_*
綜上,我們在子系統根目錄下放置的pytest.ini樣例如下,腳本運行時可以根據自己的需要修改。
# pytest.ini
[pytest]
addopts = -s --testbed="E:\Desktop\topology_template.yaml" --reportpath="E:\Desktop"
python_files = TestCase_*
python_functions = TestCase_*
下面介紹部分常用配置項
markers
為了避免自定義標記的拼寫錯誤,可以通過makers字段在pytest.ini文件中注冊標記,如有不在markers字段中的標記,pytest運行時會報錯。
[pytest]
markers =
smoke: run smoke testcase
func: run functionarity testcase
標記注冊好之后,可以通過pytest --makers來查看
五、腳本寫作
1.執行單個測試用例
創建一個.py文件(test_001.py),對個簡單的功能進行測試。
#coding=utf-8
# 方法
def func(x):
return x + 1
# 測試用例
def test_answer():
assert func(3) == 5
注意:測試用例函數命名應全部小寫,並以test_開頭,如test_answer
切換到測試文件所在的目錄,通過“pytest”命令運行測試
c:\python_ts>pytest
2.執行多個測試用例
在一個測試類中可以創建多個測試用例:
#coding=utf-8
class TestClass:
def test_one(self):
x = "this"
assert "h" in x
def test_two(self):
x = "hello"
assert x == "hi"
注意:測試類命名規范為以Test開頭
pytest指定文件運行:
>pytest -q test_002.py
-q 為quiet。表示在安靜的模式輸出報告。-q 不會輸出pytest的版本信息。
如果沒有參數,pytest會查看當前目錄和所有子目錄的測試文件(test_開頭或者
_test結尾)並運行。 也可以指定文件名,目錄名稱或這些名稱的列表。
發現規則小結
• 測試文件應該命名為test_.py 或_test.py
• 測試方法和函數應該被命名為test_。
• 測試類應該被命名為Test
結果類型:
以下是測試功能的幾種常見的結果:
• PASSED (.):測試成功。
• FAILED (F): 測試失敗。
• ERROR (E):錯誤
3.從python代碼中調用pytest
通過python代碼執行pytest
(1)直接執行pytest.main() 【自動查找當前目錄下,以test_開頭的文件或者以_test結尾的py文件】
(2)設置pytest的執行參數 pytest.main(['--html=./report.html','test_xxx.py'])【執行test_login.py文件,並生成html格式的報告】
方式2中,pytest.main()的參數其實是個list,執行參數和插件參數,多個參數時[]內的多個參數通過‘逗號,’進行分割
比如,在C:\python_testscript目錄下有三個py文件
python_testscript/
├── test_001.py
├── test_002.py
└── test_003.py
其中test_003.py的代碼如下:
import pytest
def test_main():
assert 5 != 5
if __name__ == '__main__':
pytest.main()
pytest.main不帶參數,直接運行該程序,sublime 中按Ctrl+B 運行。結果如下:
============================= test session starts =============================
platform win32 -- Python 3.7.1, pytest-4.0.2, py-1.7.0, pluggy-0.8.0
rootdir: C:\python_testscript, inifile:
plugins: metadata-1.7.0, html-1.19.0
collected 4 items
test_001.py F [ 25%]
test_002.py .F [ 75%]
test_003.py F [100%]
================================== FAILURES ===================================
_________________________________ test_answer _________________________________
def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)
test_001.py:9: AssertionError
_____________________________ TestClass.test_two ______________________________
self = <test_002.TestClass object at 0x0000000003791A90>
def test_two(self):
x = "hello"
> assert x == "hi"
E AssertionError: assert 'hello' == 'hi'
E - hello
E + hi
test_002.py:11: AssertionError
__________________________________ test_main __________________________________
def test_main():
> assert 5 != 5
E assert 5 != 5
test_003.py:4: AssertionError
===================== 3 failed, 1 passed in 0.22 seconds ======================
[Finished in 1.4s]
從執行結果看到,main() 默認執行了當前文件所在的目錄下的所有測試文件。
那么,如果我們只想運行某個測試文件呢?可以向main()中添加參數:
import pytest
def test_main():
assert 5 != 5
if __name__ == '__main__':
pytest.main(['test_001.py'])
============================= test session starts =============================
platform win32 -- Python 3.7.1, pytest-4.0.2, py-1.7.0, pluggy-0.8.0
rootdir: C:\python_testscript, inifile:
plugins: metadata-1.7.0, html-1.19.0
collected 1 item
test_001.py F [100%]
================================== FAILURES ===================================
_________________________________ test_answer _________________________________
def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)
test_001.py:9: AssertionError
========================== 1 failed in 0.06 seconds ===========================
[Finished in 1.2s]
4.常用參數說明
(1)執行失敗N條用例后停止運行
pytest -x # 第一條用例失敗后停止運行
pytest --maxfail=2 # 失敗兩條用例后停止運行
(2) 指定執行用例
pytest test_abc.py # 執行test_abc.py中的所有用例
pytest testing/ # 執行testing目錄下的所有用例
pytest test_abc.py::TestClassA::test_sample # 執行test_abc.py文件中的TestClassA測試類中的test_sample方法
pytest -v -m AR161 # 按標簽執行當前目錄下,fixture為AR1610的用例
(3)循環執行用例
pytest --count 30 # 帶--count參數指定循環次數(需要安裝pytest-repeat包)
(4) 生成測試報告
pytest --junitxml=path # 生成junit類型測試報告
pytest -v --html=testresult.html # 生成html類型測試報告
(5) cmd命令行執行過程打印信息
pytest --capture=no
(6)其他參數
pytest –v #輸出詳細信息
pytest –q #靜默模式,不輸出python的版本信息等
5.常用斷言和異常處理
(1)常用斷言:
assert a==b,”添加斷言備注信息”
assert a!=b, ”添加斷言備注信息”
assert a, ”添加斷言備注信息”
assert not a, ”添加斷言備注信息”
assert “abc” in “123abc” , ”添加斷言備注信息”
assert “ef” not in “123abc” , ”添加斷言備注信息
(2)python的標准異常
異常名稱 描述
BaseException 所有異常的基類
SystemExit 解釋器請求退出
KeyboardInterrupt 用戶中斷執行(通常是輸入^C)
Exception 常規錯誤的基類
StopIteration 迭代器沒有更多的值
GeneratorExit 生成器(generator)發生異常來通知退出
StandardError 所有的內建標准異常的基類
ArithmeticError 所有數值計算錯誤的基類
FloatingPointError 浮點計算錯誤
OverflowError 數值運算超出最大限制
ZeroDivisionError 除(或取模)零 (所有數據類型)
AssertionError 斷言語句失敗
AttributeError 對象沒有這個屬性
EOFError 沒有內建輸入,到達EOF 標記
EnvironmentError 操作系統錯誤的基類
IOError 輸入/輸出操作失敗
OSError 操作系統錯誤
WindowsError 系統調用失敗
ImportError 導入模塊/對象失敗
LookupError 無效數據查詢的基類
IndexError 序列中沒有此索引(index)
KeyError 映射中沒有這個鍵
MemoryError 內存溢出錯誤(對於Python 解釋器不是致命的)
NameError 未聲明/初始化對象 (沒有屬性)
UnboundLocalError 訪問未初始化的本地變量
ReferenceError 弱引用(Weak reference)試圖訪問已經垃圾回收了的對象
RuntimeError 一般的運行時錯誤
NotImplementedError 尚未實現的方法
SyntaxError Python 語法錯誤
IndentationError 縮進錯誤
TabError Tab 和空格混用
SystemError 一般的解釋器系統錯誤
TypeError 對類型無效的操作
ValueError 傳入無效的參數
UnicodeError Unicode 相關的錯誤
UnicodeDecodeError Unicode 解碼時的錯誤
UnicodeEncodeError Unicode 編碼時錯誤
UnicodeTranslateError Unicode 轉換時錯誤
Warning 警告的基類
DeprecationWarning 關於被棄用的特征的警告
FutureWarning 關於構造將來語義會有改變的警告
OverflowWarning 舊的關於自動提升為長整型(long)的警告
PendingDeprecationWarning 關於特性將會被廢棄的警告
RuntimeWarning 可疑的運行時行為(runtime behavior)的警告
SyntaxWarning 可疑的語法的警告
UserWarning 用戶代碼生成的警告
(3)異常處理
1)try...except
a=10
b=0
try:
c=a/b
except:
print("error")
print("done")
2)try ....except...else 語句,當沒有異常發生時,else中的語句將會被執行
a=10
b=0
try:
c = b/ a
except:
print("error")
else:
print("no error")
print("done")
3)raise 引發一個異常
inputValue=input("please input a int data :")
if type(inputValue)!=type(1):
raise ValueError
else:
print(inputValue)
4)try ...finally ,無論異常是否發生,在程序結束前,finally中的語句都會被執行
a=10
b=0
try:
c = a/ b
finally:
print("always excute")
finally語句也可以和except語句一起使用
a=10
b=0
try:
c = a/ b
except:
print("error")
finally:
print("always excute")
6.正則表達式
必須要import re
1) re.match函數
re.match 嘗試從字符串的起始位置匹配一個模式,如果不是起始位置匹配成功的話,match()就返回none。
如:
import re
print(re.match('www', 'www.123.com') .group()) # 在起始位置匹配
print(re.match('com', 'www.123.com')) # 不在起始位置匹配
輸出結果:
www
None
2)re.search方法
re.search 掃描整個字符串並返回第一個成功的匹配。
如:
import re
print(re.search('www', 'www.123.com').group())
print(re.search('com', 'www.123.com').group())
輸出結果:
www
com
re.match與re.search的區別:
re.match只匹配字符串的開始,如果字符串開始不符合正則表達式,則匹配失敗,函數返回None;而re.search匹配整個字符串,直到找到一個匹配。
3) re.findall函數
在字符串中找到正則表達式所匹配的所有子串,並返回一個列表,如果沒有找到匹配的,則返回空列表。
注意: match 和 search 是匹配一次 ,findall 匹配所有。
import re
print(re.finditer(r"\d+","12a32bc43de3"))
輸出結果:
['12', '32', '43', '3']
4) re. finditer函數
和 findall 類似,在字符串中找到正則表達式所匹配的所有子串,並把它們作為一個迭代器返回。
import re
it = re.finditer(r"\d+","12a32bc43de3")
for match in it:
print (match.group() )
輸出結果:
12
32
43
3
六、測試套特性目錄內容舉例
1.測試套即為特性目錄名,如testcase/startup,特性目錄下存放__init__.py、conftest.py以及requirements.py及測試用例腳本文件
1)__init__.py :為空文件即可,標識該目錄為一個package
2)contest.py: 定義腳本的setup和teardown,結構如下:
# --------------------------------------------------------
#
#注釋部分
#
# --------------------------------------------------------
#依賴的模塊
import os,sys
sys.path.append(os.path.split(os.path.realpath(__file__))[0])
from requirements import *
@pytest.fixture(scope='package', autouse=True)
def testuite_setup_teardown():
#准備工作:每個特性的所有用例執行前執行一次
Log.log('\n------------testsuite setup begin--------------')
dta.login()
yield
#環境清理:每個特性所有用例執行完執行一次
Log.log('\n------------testsuite teardown begin--------------')
@pytest.fixture(scope='function', autouse=True)
def testcase_setup_teardown():
#准備工作:每個用例運行前執行一次
Log.log('\n------------testcase setup begin--------------')
yield
#環境清理:每個用例運行完執行一次
Log.log('\n------------testcase teardown begin--------------')
3)requirements.py :存放所有需要依賴的模塊
######################系統模塊##########################
import time
import datetime
import re
import pytest
import sys
import os
from ctypes import *
######################pytest_testlib_base模塊##########################
import Log
import rpyc_client
import rpyc_server
######################本地自定義common模塊##########################
sys.path.append("%s/../../common/"%(os.path.split(os.path.realpath(__file__))[0]))
sys.path.append("%s/../../common/STARTUP"%(os.path.split(os.path.realpath(__file__))[0]))
import py_base
import file_method
4)測試用例腳本文件:
# --------------------------------------------------------
#
#--
# 用例編號 : TESTCASE_1001
# 用例名稱 :測試用例demo
# --------------------------------------------------------
from requirements import *
@pytest.fixture(scope='function', autouse=True)
def prepare_cleanup():
Log.log('\n------------prepare begin--------------')
yield
Log.log('\n------------cleanup begin--------------')
def TESTCASE_1001():
Log.log("操作步驟1、設備啟動,有預期結果1")
#py_base.py文件及check_startup方法定義在整個工程目錄中common文件夾中,通過requirements.py 的本地自定義common模塊聲明引入
py_base.check_startup(dev_a)
Log.log("預期結果1、設備正常啟動")