В этой статье Вы узнаете о том как можно тестировать ПО с помощью Python.
Я начну с подготовки рабочей среды, затем перейдём к простым заданиям, которые
могут поручить начинающему тестировщику.
На следующем этапе рассмотрим библиотеку unittest и изучим немного теории.
Статья рассчитана на начинающих тестировщиков. Для лучшего понимания некоторых
частей желательно базовое знание
Python
Introduction | |
Документация | |
Подготовка рабочей среды | |
Учебный пример | |
Реальный пример 1 | |
unittest | |
Теория unittest | |
pytest | |
Решение проблем | |
Другие статьи о Python | |
Другие статьи о Тестировании |
Использование Python для тестирования ПО.
docs.python-requests
programcreek.com/python
To отправлять POST, GET и другие HTTP запросы с помощью python нужно в текст программы добавить строчку import requests. Request сперва нужно установить, для этого нужен pipenv, а для установки pipenv нужен pip
sudo apt install python-pip
Если нужно обновить pip
pip install --upgrade pip
Устанавливаем pipenv
pip install pipenv
Прежде чем устанавливать что-либо кроме pip убедитесь в том, что Вы знакомы с работой в virtual environment.
Устанавливаем requests
pipenv install requests
Теперь наше python окружение готово к тестированию интерфейсов.
На вашем компьютере может быть установлено несколько версий Python. To узнать
какую версию используют ваши программы перейдтие по
ссылке
Создаем файл post.py и пишем следующий код
import requests
r = requests.post('http://url.html', data = {'site':'aredel.com'})
Запускаем скрипт
python post.py
Есть сервер, на котором отображаются подключённые устройства. Назовем его
Менеджер_Устройств
Задача - заселить сервер новыми устройствами, количество - 1000 устройств.
Нужно, чтобы у каждого устройства был
уникальный ID. Иначе получим ошибку.
Познакомившись с
API этого сервера
можно узнать, что запрос, которым добавляется новое устройство, выглядит
следующим образом:
PUT to http://devm.com:4880/manager/rest/control/devices/Unique_ID/apps/Client_Name/status/$timestamp=Some_value
Также из API известно, что в этом запросе передаётся JSON
{"status":
{"clientStatusData":
{"message":"Everything is OK",
"status":"OK"
},
"itemsStatuses":
[{
"message":"URN.SU Server simulated",
"status":"ENABLED",
"name":"Connection",
"Number":"0"
},
{
"message":"TopBicycle.RU Power: 250[mW], Session: 1",
"status":"OK",
"name":"AndreyOlegovih.ru",
"Number":"1"
}],
"runningStatus":
{
"restarted":"true",
"uptimeMSec":10000}
},
"clientInfo":
{
"applicationInfo":{"applicationVersion":"19.61.04.12"
},
"deviceInfo":
{"itemDescription": "Good Device Number 1",
"itemModelId":"Model ID 1",
"statusUpdateIntervalMSec":"30000"
}
},
}
По заданию: itemModelId , itemDescription и uptime нужно делать уникальными.
Таким образом уникальных величины должно быть четыре.
Можно, конечно, посылать запросы из
SOAP UI
по одному, вручную изменяя Unique_ID, но это будет очень долго.
Пишем скрипт на Python, испльзуя знания, полученные в начале этой статьи и в статье
Python. Сначала импортируем нужные библиотеки.
Затем делим URL на три части: первая и третья остаются неизменными, а между ними мы будем вставлять
переменую.
После этого запускаем цикл от 1 до 1000. Значения переменной i мы будем использовать для создания
уникальных ID. С этой целью создадим три переменные: для наглядности они все будут заканчиваться на
_var а затем я выделю их зелёным цветом.
И, наконец, создаём переменную json_string, в которую запишем нужный нам JSON с небольшими изменениями.
Вместо статичных itemModelId , itemDescription, uptime вставляем переменные
заданные на предыдущем шаге.
Внимательно следим за отступами, т.к. отступ обозначает тело цикла.
import requests
import json
import urllib2
import uuid
headers = {"Content-Type": "application/json"}
base_url='http://device_manager.com:4880 / manager / rest /control / devices /'
end_url=' / apps / Client_Name / status /$timestamp=1529086249'
for i in range(1,1000):
c=str(i)
item_model_var="AASuperDevice"+c
item_description_var="Andrei"+c
uptime_var=i * 50
Unique_ID_var="Unique_ID"+c
url=base_url+str(Unique_ID_var)+end_url
json_string= {"status":
{"clientStatusData":
{"message":"Everything is OK",
"status":"OK"
},
"itemsStatuses":
[{
"message":"URN.SU Server simulated",
"status":"ENABLED",
"name":"Connection",
"Number":"0"
},
{
"message":"TopBicycle.RU Power: 250[mW], Session: 1",
"status":"OK",
"name":"AndreyOlegovih.ru",
"Number":"1"
}],
"runningStatus":
{
"restarted":"true",
"uptimeMSec":uptime_var}
},
"clientInfo":
{
"applicationInfo":{"applicationVersion":"19.61.04.12"
},
"deviceInfo":
{"itemDescription": item_description_var,
"itemModelId":item_model_var,
"statusUpdateIntervalMSec":"30000"
}
},
}
data_json=json.dumps(json_string)
r=requests.put(url, data=data_json, headers=headers)
Если что-то пошло не так можно попробовать простейший способ отследить в какой момент появляется ошибка -
добавить в конец кода
print ("i =", i)
print ("i string=", c)
print (item_model_var)
print (u)
print (uptime_var)
print(r.text)
Но имейте в виду, что в серьёзном софте лучше делать отладку дебаггером.
unittest это библиотека для тестирования, которая входит в Python по умолчанию
Разберём простейший пример использования.
Создадим два файла calc.py и test_calc.py
#calc.py
def add(x, y):
"""Add Function"""
return x + y + 3
def subtract(x, y):
"""Subtract Function"""
return x - y
def multiply(x, y):
"""Multiply Function"""
return x * y
def divide(x, y):
"""Divide Function"""
if y == 0:
raise ValueError("Can not divide by zero!")
return x / y
Как видите, в функции add специально допущена ошибка - вместо сложения двух переменных к ним ещё добавляется число 3
#test_calc.py
import unittest
import calc
#https://docs.python.org/3/library/unittest.html#unittest.TestCase.debug
class TestCalc(unittest.TestCase):
def test_add(self):
result = calc.add(10, 5)
self.assertEqual(result, 15)
#python3 -m unittest test_calc.py
Для запуска теста перейдём в директорию с файлами и в консоли выполним команду
python3 -m unittest test_calc.py
F ====================================================================== FAIL: test_add (test_calc.TestCalc) ---------------------------------------------------------------------- Traceback (most recent call last): File "/mnt/c/Users/username/python/unittest/test_calc.py", line 10, in test_add self.assertEqual(result, 15) AssertionError: 18 != 15 ---------------------------------------------------------------------- Ran 1 test in 0.001s FAILED (failures=1)
Исправим ошибку
#calc.py
def add(x, y):
"""Add Function"""
return x + y
...
python3 -m unittest test_calc.py
. ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
To запустить этот тест в PyCharm или запускать его из консоли, но без дополнительного указания -m unittest добавим в конец файла test_calc.py две строчки:
#test_calc.py
...
if __name__ == '__main__':
unittest.main()
Теперь можно запускать тест командой
python3 test_calc.py
Напишем тесты для всех функций из calc.py
Снова специально допустим ошибку, например, в третьем тесте
import unittest
import calc
class TestCalc(unittest.TestCase):
def test_add(self):
self.assertEqual(calc.add(10, 5), 15)
self.assertEqual(calc.add(-1, 1), 0)
self.assertEqual(calc.add(-1, -1), -2)
def test_subtract(self):
self.assertEqual(calc.subtract(10, 5), 5)
self.assertEqual(calc.subtract(-1, 1), -2)
self.assertEqual(calc.subtract(-1, -1), 0)
def test_multiply(self):
self.assertEqual(calc.multiply(10, 5), 70)
self.assertEqual(calc.multiply(-1, 1), -1)
self.assertEqual(calc.multiply(-1, -1), 1)
def test_divide(self):
self.assertEqual(calc.divide(10, 5), 2)
self.assertEqual(calc.divide(-1, 1), -1)
self.assertEqual(calc.divide(-1, -1), 1)
if __name__ == '__main__':
unittest.main()
Запустим тест
python3 test_calc.py
..F. ====================================================================== FAIL: test_multiply (__main__.TestCalc) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:/Users/username/.PyCharmCE2018.3/config/scratches/test_calc.py", line 17, in test_multiply self.assertEqual(calc.multiply(10, 5), 70) AssertionError: 50 != 70 ---------------------------------------------------------------------- Ran 4 tests in 0.001s FAILED (failures=1) Process finished with exit code 1
Обратите внимание на первую строчку, точки означают успешное выполнение теста. F - провал теста.
..F. означает, что первый, второй и четвёртый тесты прошли успешно, а в третьем ошибка
Assertion который вернул FALSE также виден self.assertEqual(calc.multiply(10, 5), 70)
И ошибка AssertionError: 50 != 70
Имея такой подробный результат мы легко исправляем ошибку
self.assertEqual(calc.multiply(10, 5), 70)
Меняем на
self.assertEqual(calc.multiply(10, 5), 50)
Запустим тест
python3 test_calc.py
.... ---------------------------------------------------------------------- Ran 4 tests in 0.001s OK Process finished with exit code 0
Для тех, кто интересуется устарел ил unittest или нет, моё скромное мнение состоит в том, что нет.
В мире Python более модным считается PyTest одна из причин - более простой синтаксис.
Тем не менее
unittest удобен тем, что он встроен в стандартную библиотеку и тем, что
в других языках программирования тоже есть похожие фреймворки.
Единичный тест называется тест кейсом (Test Case).
Часто нужно запустить несколько тест-кейсов, которым требуется для запуска одно и то же.
Например, получить один и тот же объет или запустить
Selenium Webdriver
или что-то другое.
To не писать в каждом тест-кейсе одно и то же можно воспользоваться методами
setUp и tearDown которые создаются один раз для каждого класса и будут запускаться перед
каждым тест-кейсом.
Такая комбинация setUp + tearDown называется
Test Fixture
Test Fixture = setUp + tearDown
Порядок выполнения тестов обычно следующий:
Подготовка к тесту
Непосредственное действие, например, запуск определённой функции
Проверка результата на соответствие ожиданию.
Arrange → Act → Assert
Длинных тестов в которых происходит множество чередующихся действий и проверок
следует по возможности избегать.
Лучше написать несколько небольших тестов чем один длинный. Тогда при фэйле какого-то из
хорошо структурированных тестов будет легче понять, что именно не работает.
Settings (Ctrl + Alt + S) → Tools → Python Integrated Tools →
Default test runner:
Выбрать pytest. Если он ещё не был добавлен появится предупреждение
и кнопка Fix.
Нужно нажать кнопку Fix
Нужно импортировать pytest.
import pytest
API testing lessons | |
API testing | |
Selenium + Python | |
SOAP UI | |
JMeter | |
Bash for QA Engineer | |
Clumsy 0.2 | |
Python script for ZPL | |
Python Sockets | |
Integration Testing |
Share in social media:
|