July 28, 2018

Тестируем код в Python: unittest

Вспомните, когда вы в последний раз писали программу и она запускалась с первого раза, и в ней потом не было найдено багов. Тоже вспомнили "Hello world!"?;) Написание кода, а особенно длинного, требует огромной внимательности, однако даже если вы ей обладаете, то не факт, что в вашем коде не будет проблем. Бывает так, что о них вы узнаёте через продолжительное время, в самый неподходящий момент. Так как же предупредить эти самые проблемы? Очевидно, надо тестировать свою программу. Однако как? Не вручную же вбивать много разных данных в функции и смотреть, тот ли результат. Постойте, мы же с вами написали какую-то программу, а что нам мешает написать другую программу, которая будет тестировать первую? Специально для таких программ в стандартной библиотеке python есть модуль unittest.

Код с подсветкой можете найти на Pastebin:
Файл с функцией: https://pastebin.com/NH5FmLSc
Файл с тестами: https://pastebin.com/BtqXuNiK

Давайте напишем функцию для получения чисел Фибоначчи в файле, который назовём fibonacci.py

def get_fibonacci_numbers(amount):                        
  if amount == 1:                               
    return [1]                                
  result = [1, 1]                               
  for i in range(amount-2):                          
    result.append(result[-1] + result[-2])                  
  return result

Теперь напишем программу, которая будет тестировать эту функцию. Для этого в модуле unittest есть класс TestCase, от которого можно наследоваться и создавать тестирующей класс. У объекта этого класса есть специальные методы вида assert<что-то ещё>, которые сравнивают разные значения с ожидаемыми. Самым распространённым является метод assertEqual, который сравнивает 2 значения и, в случае различия, выдаёт ошибку. Давайте напишем самый простой тест для одного числа в файле fibtest.py

from unittest import TestCase                          
from fibonacci import get_fibonacci_numbers                   
                                         
                                         
class FibonacciTest(TestCase):                        
  def test_single(self):                            
    self.assertEqual(1, get_fibonacci_numbers(1)[0]) 

Мы создаём у этого класса тестирующий метод, название которого обязательно должно начинаться со слова test(требование программы-тестера). Давайте напишем ещё один тест посложнее, который будет проверять всю последовательность на каком-нибудь числе

from unittest import TestCase                          
from fibonacci import get_fibonacci_numbers                   
                                         
                                         
class FibonacciTest(TestCase):                          
  def test_single(self):                            
    self.assertEqual(1, get_fibonacci_numbers(1)[0])             
                                         
  def test_big_number(self):                          
    big_number = 1337                            
    sequence = get_fibonacci_numbers(big_number)               
    self.assertEqual(1, sequence[0])                     
    self.assertEqual(1, sequence[1])                     
    for i in range(2, big_number):                      
      self.assertEqual(sequence[i-1] + sequence[i-2], sequence[i])  

Тесты есть, осталось их запустить. Для этого надо выполнить команду test из модуля unittest на нашем файле:

python -m unittest test fibtest.py

Вывод у команды будет следующего вида:

----------------------------------------------------------------------
Ran 2 tests in 0.003s

OK

Статус OK говорит, что все тесты пройдены успешно. Если бы были ошибки, то там была бы информация о них. Вот так вот можно стандартными средствами тестировать программы.

Надеюсь, статья была вам полезной.

Буду рад видеть вас в группе SnakeBlog