Виконання завдань по роботі в ІТ галузі.
Це процес перевірки правильності роботи програм, їх функцій та поведінки при різних умовах роботи шляхом створення штучних ситуацій або сценаріїв.
assert - це перевірка певних тверджень та встановлення працездатності коду. Твердження дозволяють перевірити правильність коду, перевіряючи, чи виконуються певні умови.
number = -1
assert number > 0, "число має бути більшим за нуль!"
assert та зробіть тестові превірки при введенні даних з клавіатури. Для цього використайте метод input як показано нижче:
a = input("Введіть число: ")
assert a.isdigit(), "Потрібно ввести число!"
print(f"введене число: {a}")
assert найкраще виконувати для перевірки (валідації) правильності вводу аргументів. Для прикладу маємо простий клас в якому здійснюємо валідацію даних перед тим як створювати обєкт. Умовою валідації може бути будь-який вираз Python який повертає значення True/False.
class Figure:
def __init__(self, type, length) -> None:
assert length > 0, "Довжина має бути більшою за 0!"
assert type in ["квадрат", "прямокутник", "трикутник"], "Дозволені фігури: квадрат, прямокутник, трикутник"
self.type = type
self.length = length
#a = Figure("трапеція", 12)
#b = Figure("квадрат", 0)
c = Figure("квадрат", 1)
class Name:
def __init__(self, name) -> None:
if name not in ["Богдан", "Анонім"]:
raise ValueError("Дозволені імена: Богдан, Анонім")
self.name = name
a = Name("Бодько")
Це перевірка малої частини коду, юніта. Найчастіше це порівняння між введеними даними та результатом виконання якоїсь частини програми.
unittest. Зазвичай юніт тести створюються в окремому файлі, однак в межах проекту який має бути протестованим.app.py. Це буди потрібно для імпорту бібліотек (класів).
class Figure:
FIGURES = ["квадрат", "прямокутник", "трикутник"]
def __init__(self, type, length) -> None:
assert length > 0, "Довжина має бути більшою за 0!"
assert type in self.FIGURES, "Дозволені фігури: квадрат, прямокутник, трикутник"
self.type = type
self.length = length
@property
def get_figure_type(self):
return self.type
@property
def get_figure_length(self):
return self.type # робимо помилку
setUp з допомогою бібліотеки random створимо обєкт та перевіримо чи правильно працюють методи:
import unittest
from random import choice, randint
from app import Figure # назва файлу з нашим класом повинна бути app.py
class TestFigure(unittest.TestCase):
@classmethod
def setUpClass(cls):
"""Виконається лише раз на початку тестів
"""
pass
def setUp(self) -> None:
"""Виконується кожного разу коли запускається тест
"""
self.figure = choice(Figure.FIGURES)
self.length = randint(1, 10)
self.obj = Figure(self.figure, self.length)
return super().setUp()
def tearDown(self) -> None:
del self.obj
return super().tearDown()
def test_figure_type(self):
print(f"Тестуємо вивід, має бути: {self.figure} == {self.obj.get_figure_type}")
self.assertEqual(self.figure, self.obj.get_figure_type, "Властивість get_figure_type повертає непривильну фігуру!")
def test_figure_lengh(self):
self.assertEqual(self.length, self.obj.get_figure_length, "Властивість get_figure_length повертає непривильну довжину!")
def test_obj(self):
with self.assertRaises(AssertionError):
Figure("коло", 1) # Спробуємо створити обєкт з недозволеними параметрими, в нас має бути помилка AssertionError
if __name__ == '__main__':
unittest.main() # unittest.main(verbosity=2) щоб був більш детальний вивід
unittest.main(), то програму можна викликати з Visual Studio Code через кнопку Run (трикутник :arrow_forward:) або який регулярний Python файл:
python test.py
unittest.main()), потрібно виконати команду з явним викликом бібліотеки unittest. Для більш детального виводу просто додайте опцію -v або --verbose:
python -m unittest
__pycache__ яку не варто комітити в репозиторій, тому додайте її в .gitignore.PyTest це стороння бібліотета для тестування коду
pipenv або poetry (якщо pipenv буде некоректно працювати на Windows встановіть бібліотеку за допомогою pip). Бібліотеки для юніт тестів краще ставити в --dev середовище.
pipenv --python 3.12
pipenv install pytest --dev
pipenv install --dev
# або
poetry init --name your_project --description "Your project description" --author "Your Name <your@email.com>"
poetry add --dev pytest black flake8
poetry install --with dev
test_. Для прикладу зробимо простий тест та помістимо всередині того ж файлу де і наш клас Figure:
app.py:
def test_app_triangle():
"""Test if we create triangle figure.
"""
fig = "трикутник"
triangle = Figure(fig, 4)
assert triangle.type == fig, f"Фігура має бути {fig}"
pytest:
poetry run pytest app.py
test_app_triangle.test.py потібно передати даний файл як аргумент pytest:
poetry run pytest test.py
Допоміжна бібліотека для збору статистика покриття коду юніт тестами. Покриття тестами - це відношення між кількістю рядків, виконаних хоча б одним тестом, до загальної кількості рядків кодової бази.
pipenv install coverage pytest-cov --dev
# АБО
poetry add --dev coverage pytest-cov
coverage або передавати аргументи у виклик pytest.
poetry run python -m unittest discover
# АБО - якщо всі тести поміщені в окрему папку під назвою tests
poetry run python -m unittest discover -s tests -v
# АБО - використовуючи бібліотеку pytest
poetry run pytest -v
coverage (у репозиторії має зявитись файл .coverage):
poetry run python -m coverage report
# АБО запуск того самого тестування unittest але вже з coverage
poetry run coverage run -m unittest discover -s tests -v
# АБО тестування з використанням бібліотеки pytest
poetry run coverage run -m pytest
pytest. Тут ми передаємо параметр який саме модуль ми хочемо проаналізувати. В даному випадку наша бібліотека з класом знаходиться в файлі app.py тому ми передаємо параметр --cov=app:
poetry run pytest --cov=app test.py
Figure наступний код:
@property
def get_angles(self):
if self.type in ["квадрат", "прямокутник"]:
return 4
if self.type == "трикутник":
return 3
def test_get_angles():
"""Тестуємо чи правильно повертається кількість кутів фігури.
"""
fig = "трикутник"
triangle = Figure(fig, 1)
assert triangle.get_angles == 3, f"У {fig} є 3 кути!"
poetry run python -m coverage report
html. Відкрийте файл index.html у веб-браузері та дослідіть отриману інформацію. Отриманий файл повинен бути у звіті.
poetry run python -m coverage html
.coveragerc з наступним вмістом:
[run]
source = app.py
[report]
omit =
*/__init__.py
*/tests/*
*/venv/*
і знову виконайте генерацію звіту та проаналізуйте отримані результати:
poetry run python -m coverage html
виконання тестів можна автоматизувати що буде зроблено в наступній роботі
- Всі тести та їх виконання яке здійснювалось вручну у цій роботі буде потрібним для наступної.
- Автоматизація виконується щодо команд запуску тестів та результату їх роботи.