GeekBrains
РОСБАНК [CPS] RU
Dfsport
↑↑

↓↓
Флаг России Флаг Англии
🏠 | 💻 PC | 🔨Тестирование ПО |

Использование Python для тестирования ПО

Введение

В этой статье Вы узнаете о том как можно тестировать ПО с помощью Python.

Я начну с подготовки рабочей среды, затем перейдём к простым заданиям, которые могут поручить начинающему тестировщику.

На следующем этапе рассмотрим библиотеку unittest и изучим немного теории.

Статья рассчитана на начинающих тестировщиков. Для лучшего понимания некоторых частей желательно базовое знание Python

Использование Python для тестирования ПО.

docs.python-requests

programcreek.com/python

Подготовка рабочей среды

Чтобы отправлять POST, GET и другие HTTP запросы с помощью python нужно в текст программы добавить строчку import requests. Request сперва нужно установить, для этого нужен pipenv, а для установки pipenv нужен pip

sudo apt install python-pip

Если нужно обновить pip

pip install --upgrade pip

Устанавливаем pipenv

pip install pipenv

Устанавливаем requests

pipenv install requests

Теперь наше python окружение готово к тестированию интерфейсов.

На вашем компьютере может быть установлено несколько версий Python. Чтобы узнать какую версию используют ваши программы перейдтие по ссылке

Примеры программ

Создаем файл post.py и пишем следующий код

import requests r = requests.post('http://url.html', data = {'site':'andreyolegovich.ru'})

Запускаем скрипт

python post.py

Реальный пример 1

Задача

Есть сервер, на котором отображаются подключённые устройства. Назовем его Менеджер_Устройств

Задача - заселить сервер новыми устройствами, количество - 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, но это будет очень долго.

Решение. Часть 1 - Комментарии

Пишем скрипт на Python, испльзуя знания, полученные в начале этой статьи и в статье Python. Сначала импортируем нужные библиотеки.

Затем делим URL на три части: первая и третья остаются неизменными, а между ними мы будем вставлять переменую.

После этого запускаем цикл от 1 до 1000. Значения переменной i мы будем использовать для создания уникальных ID. С этой целью создадим три переменные: для наглядности они все будут заканчиваться на _var а затем я выделю их зелёным цветом.

И, наконец, создаём переменную json_string, в которую запишем нужный нам JSON с небольшими изменениями. Вместо статичных itemModelId , itemDescription, uptime вставляем переменные заданные на предыдущем шаге.

Внимательно следим за отступами, т.к. отступ обозначает тело цикла.

Решение. Часть 2 - Код

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)

Debugging

Если что-то пошло не так можно попробовать простейший способ отследить в какой момент появляется ошибка - добавить в конец кода

print ("i =", i) print ("i string=", c) print (item_model_var) print (u) print (uptime_var) print(r.text)

Но имейте в виду, что в серьёзном софте лучше дебажить дебаггером.

Unittest

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

Чтобы запустить этот тест в 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

Test Fixture

Единичный тест называется тест кейсом (Test Case).

Часто нужно запустить несколько тест-кейсов, которым требуется для запуска одно и то же.

Например, получить один и тот же объет или запустить Selenium Webdriver или что-то другое.

Чтобы не писать в каждом тест-кейсе одно и то же можно воспользоваться методами setUp и tearDown которые создаются один раз для каждого класса и будут запускаться перед каждым тест-кейсом.

Такая комбинация setUp + tearDown называется Test Fixture

Test Fixture = setUp + tearDown

Составляющие части любого теста

Порядок выполнения тестов обычно следующий:

Подготовка к тесту

Непосредственное действие, например, запуск определённой функции

Проверка результата на соответствие ожиданию.

Arrange → Act → Assert

Длинных тестов в которых происходит множество чередующихся действий и проверок следует по возможности избегать.

Лучше написать несколько небольших тестов чем один длинный. Тогда при фэйле какого-то из хорошо структурированных тестов будет легче понять, что именно не работает.

Pytest

Добавить Pytest в Pycharm

Settings (Ctrl + Alt + S) → Tools → Python Integrated Tools → Default test runner:

Выбрать pytest. Если он ещё не был добавлен появится предупреждение и кнопка Fix.

Нужно нажать кнопку Fix

Ошибки

NameError: name 'pytest' is not defined

Нужно импортировать pytest.

import pytest

GeekBrains Clumsy 0.2 Soap UI
Курсы тестирования ПО
Тестирование с помощью Python 🖄Postman
Nmap Webservices
Тестирование API Testlink
Pivotal Tracker 🦈 Wireshark

Если сайт не помог, извиняемся за потраченное время - хочу заверить, что мы стараемся не попадать в нерелевантные запросы, но тем не менее не всегда успеваем обновлять ключевые слова. Ну и контролировать поисковую выдачу, конечно, невозможно.

Например: у нас есть статья про аэропорт Хельсинки и про аэропорт Риги но в выдаче по Риге всё равно статья про Хельсинки.

Если статья Вам помогла, нажимайте ДА. Так мы поймём, что переделывать её не нужно.

Занятно наблюдать в вебвизоре, как люди копируют текст, например вежливого отказа в трудоустройстве на английском но игнорируют кнопку ДА.

Сделаем поиск лучше!

Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@urn.su если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящуюю по тематике.
3. Реклама на моём сайте имеет максимальный уровень цензуры. Если Вы увидели рекламный блок недопустимый для просмотра детьми школьного возраста, вызывающий шок или вводящий в заблуждение - пожалуйста свяжитесь с нами по электронной почте
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......
5. Статьи можно расшарить в соцсетях, нажав на иконку сети: