Python. Unit test (Юнит-тесты)

Всем известно, что тестирование программ важно и актуально. Но, зачастую процесс прохождения кейс-тестов довольно трудоёмкий и утомительный. Именно поэтому во многих средах и языках программирования существуют различные средства автоматизации тестов. Одно из таких средств — так называемые «Unit — test». Что это такое? Понятие юнит-теста приходит из объектно-ориентированного программирования. Мы объявляем класс, который должен обладать заданным поведением.  Причём, если мы вдруг решили взять и изменить этот класс, то его поведение не должно сломаться. Для того, чтобы проверить, что поведение класса не изменилось, при помощи специальных средств создаться программы, называемые юнит тестами. Они в нужной последовательности вызывают методы класса, выдавая им определённые данные и смотрят, чтобы на выходе было то, что нужно. Если это не так, то выдается сообщения об ошибке.

Нечто подобное есть и в Python-е. Давайте сделаем это на примере одной функции, которая в качестве параметра получает имя и фамилию, а возвращает строку, содержащее имя и фамилию, разделённую пробелом:

def get_formatted_name(first, last):
    """Строит отформатированное полное имя."""
    full_name = first + ' ' + last
    return full_name.title()

Испытаем ее:

print("Введите 'q' в любое время, чтобы выйти.")
while True:
    first = input("\nВведите ваше имя: ")
    if first == 'q':
        break
    last = input("Введите вашу фамилию: ")
    if last == 'q':
        break
    formatted_name = get_formatted_name(first, last)
    print("\tВаши отформатированные имя и фамилия: " + formatted_name + '.')

Работая с программой, вы увидите примерно такой диалог:

Допустим, вы решили изменить функцию get_formatted_name(), чтобы она также работала отчествами. При этом необходимо проследить за тем, чтобы функция не перестала правильно работать для имен, состоящих только из имени и фамилии.

Пишем юнит тест

import unittest #Библиотека инстурментария юнит-тестов
from name_function import get_formatted_name #Наша функция

#Тестировочный класс
class NamesTestCase(unittest.TestCase):
    """Тесты для 'name_function.py'."""
    def test_first_last_name(self):
        """Имена вида 'Иванов Иван' работают правильно?"""
        formatted_name = get_formatted_name('иванов', 'иван')
        self.assertEqual(formatted_name, 'Иванов Иван')
        
unittest.main()

Запускам тест и видим, что все ОК:

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

А теперь доработаем нашу функцию, чтобы она выводила еще и отчество:

def get_formatted_name(first, last, middle=''):
    """Строит отформатированное полное имя."""
    full_name = first + ' ' + middle+' '+last
    return full_name.title()

И дорабатываем наш тест. Помним о том, что функция должна корректно выводить и когда указаны только Фамилия и Имя, и когда указаны Фамилия, Имя и Отчество:

import unittest #Библиотека инстурментария юнит-тестов
from name_function import get_formatted_name #Наша функция

#Тестировочный класс
class NamesTestCase(unittest.TestCase):
    """Тесты для 'name_function.py'."""
    def test_first_last_name(self):
        """Имена вида 'Иванов Иванович Иван' работают правильно?"""
        formatted_name = get_formatted_name('иванов','иван','иванович')
        self.assertEqual(formatted_name, 'Иванов Иванович Иван')    
        
        """Имена вида 'Иванов Иван' работают правильно?"""
        formatted_name = get_formatted_name('иванов', 'иван')
        self.assertEqual(formatted_name, 'Иванов Иван')    
        
unittest.main()

И опаньки, а функцию то мы сломали:

Что делаем? Исправляем:

def get_formatted_name(first, last, middle=''):
    """Строит отформатированное полное имя."""
    if middle:
        full_name = first + ' ' + middle+' '+last
    else:
        full_name = first + ' ' + last
    return full_name.title()

Теперь все работает правильно:

 

Comments

So empty here ... leave a comment!

Добавить комментарий

Sidebar