Unittest.TestCase.assertEqual: примеры (PYTHON)
unittest.TestCase.assertEqual(first, second, msg): NoneОсновы метода assertEqual
Метод assertEqual принадлежит классу unittest.TestCase и предназначен для проверки равенства двух объектов в модульном тестировании. Его применение актуально в сценариях, где требуется убедиться, что фактический результат работы функции или метода соответствует ожидаемому значению.
Синтаксис и параметры:
Основная форма вызова: self.assertEqual(first, second, msg=None).
- first: фактическое значение, полученное в ходе теста.
- second: ожидаемое значение, с которым происходит сравнение.
- msg (необязательный): строка сообщения, которая выводится при провале теста (AssertionError). Если параметр не указан, генерируется стандартное сообщение об ошибке.
Метод не возвращает значения. При успешном сравнении выполнение теста продолжается. В случае неравенства объектов возбуждается исключение AssertionError.
Внутренняя реализация использует оператор == для сравнения. Для проверки неравенства существует парный метод assertNotEqual.
Базовые примеры применения
Простейший случай сравнения чисел.
import unittest
class TestMath(unittest.TestCase):
def test_sum(self):
self.assertEqual(5 + 3, 8)
if __name__ == '__main__':
unittest.main(). ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
Сравнение строк с использованием необязательного сообщения.
import unittest
class TestString(unittest.TestCase):
def test_greeting(self):
name = 'Alex'
greeting = f'Hello, {name}'
self.assertEqual(greeting, 'Hello, Alex', msg='Строки не совпадают')
if __name__ == '__main__':
unittest.main(). ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
Сравнение списков. Метод корректно работает с коллекциями.
import unittest
class TestList(unittest.TestCase):
def test_squares(self):
result = [x**2 for x in range(5)]
self.assertEqual(result, [0, 1, 4, 9, 16])
if __name__ == '__main__':
unittest.main(). ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
Пример проваленного теста, демонстрирующий вывод.
import unittest
class TestFail(unittest.TestCase):
def test_division(self):
self.assertEqual(10 / 2, 4) # Ожидается 5
if __name__ == '__main__':
unittest.main()F
======================================================================
FAIL: test_division (__main__.TestFail)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 5, in test_division
self.assertEqual(10 / 2, 4)
AssertionError: 5.0 != 4
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)Похожие методы в Python
Библиотека unittest предлагает несколько специализированных методов сравнения.
assertNotEqual(first, second, msg=None): проверяет, что два значения не равны. Противоположность assertEqual.
self.assertNotEqual(1, 2) # Тест пройдетassertTrue(expr, msg=None) и assertFalse(expr, msg=None): проверяют истинность или ложность выражения. Более общие, но менее информативны при провале, чем assertEqual для сравнения булевых значений.
self.assertTrue(1 == 1) # Эквивалентно self.assertEqual(1, 1)
self.assertFalse(1 == 2)assertIs(first, second, msg=None): проверяет идентичность объектов (оператор is). Используется для сравнения с None или проверки, что это один и тот же объект в памяти.
self.assertIs(None, some_var) # Предпочтительнее self.assertEqual для None
self.assertIs(a, b) # Проверка, что a и b - один объектassertAlmostEqual(first, second, places=7, msg=None, delta=None) и assertNotAlmostEqual: предназначены для сравнения чисел с плавающей точкой с учетом погрешности (places - знаки после запятой, delta - абсолютная погрешность). Более надежны, чем assertEqual для float.
self.assertAlmostEqual(0.1 + 0.2, 0.3, places=7) # Тест пройдет
# self.assertEqual(0.1 + 0.2, 0.3) # Может упасть из-за погрешностиВыбор метода: Для сравнения конкретных значений на равенство используют assertEqual. Для проверки истинности сложного выражения - assertTrue/False. Для сравнения чисел с плавающей точкой - assertAlmostEqual. Для проверки идентичности, особенно с None, - assertIs/IsNot.
Аналоги в других языках программирования
JavaScript (Jest, Node.js assert): В Jest используется функция expect().toBe() для строгого равенства (аналог assertIs) и expect().toEqual() для рекурсивного сравнения значений (аналог assertEqual).
// Jest
test('addition', () => {
expect(2 + 2).toBe(4); // Строгое равенство
expect([1, 2]).toEqual([1, 2]); // Глубокое сравнение
});Тест проходит
Java (JUnit): Используются статические методы класса org.junit.Assert, например assertEquals(expected, actual). Порядок аргументов (ожидаемое, фактическое) часто обратный по сравнению с Python.
import org.junit.Assert;
import org.junit.Test;
public class TestExample {
@Test
public void testSum() {
Assert.assertEquals(4, 2 + 2);
}
}Тест проходит
PHP (PHPUnit): Метод $this->assertEquals($expected, $actual). Как и в Python, поддерживает необязательный третий аргумент - сообщение.
public function testSum(): void
{
$this->assertEquals(4, 2 + 2, 'Сложение не работает');
}Тест проходит
C# (NUnit/xUnit): В NUnit: Assert.AreEqual(expected, actual). В xUnit: Assert.Equal(expected, actual).
// xUnit
[Fact]
public void TestSum()
{
Assert.Equal(4, 2 + 2);
}Тест проходит
Golang (testing): Используются функции из пакета testing, например, if got != want { t.Errorf(...) }. Специального метода assert нет, идиоматично использовать простое сравнение.
func TestSum(t *testing.T) {
got := 2 + 2
want := 4
if got != want {
t.Errorf("got %d, want %d", got, want)
}
}Тест проходит
Kotlin (Kotlin Test/JUnit): assertEquals(expected, actual) из kotlin.test.
import kotlin.test.Test
import kotlin.test.assertEquals
class TestExample {
@Test
fun testSum() {
assertEquals(4, 2 + 2)
}
}Тест проходит
Lua (luaunit): lu.assertEquals(actual, expected). Порядок аргументов аналогичен Python.
require('luaunit')
function testSum()
lu.assertEquals(2 + 2, 4)
end
os.exit(lu.LuaUnit.run())Тест проходит
SQL (PL/pgSQL, Unit Testing): В рамках процедурных расширений, например, для PostgreSQL в pgTAP есть функция is().
BEGIN;
SELECT plan(1);
SELECT is(2 + 2, 4, '2+2 should be 4');
SELECT * FROM finish();
ROLLBACK;ok 1 - 2+2 should be 4
Основные отличия от Python: порядок аргументов (ожидаемое/фактическое), наличие или отсутствие встроенного модуля тестирования, строгость сравнения (значение vs идентичность).
Распространенные ошибки
1. Неверный порядок аргументов. Фактический результат часто путают с ожидаемым, что усложняет чтение сообщений об ошибках.
import unittest
class TestOrder(unittest.TestCase):
def test_order(self):
result = some_function() # Возвращает 5
# Нежелательно: сначала ожидаемое, потом фактическое
self.assertEqual(5, result) # Работает, но неидеально
# Предпочтительный порядок: self.assertEqual(result, 5)
if __name__ == '__main__':
unittest.main()2. Сравнение чисел с плавающей точкой. Прямое сравнение float из-за погрешностей ведет к нестабильным тестам.
import unittest
class TestFloat(unittest.TestCase):
def test_float_fail(self):
self.assertEqual(0.1 + 0.2, 0.3) # Может упасть
def test_float_correct(self):
self.assertAlmostEqual(0.1 + 0.2, 0.3, places=7)
if __name__ == '__main__':
unittest.main().F
======================================================================
FAIL: test_float_fail (__main__.TestFloat)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 5, in test_float_fail
self.assertEqual(0.1 + 0.2, 0.3)
AssertionError: 0.30000000000000004 != 0.3
----------------------------------------------------------------------
Ran 2 tests in 0.000s
FAILED (failures=1)3. Сравнение разнотипных объектов, которые могут быть равны при приведении. Python допускает сравнение некоторых разных типов (например, 1 == True, 0 == False).
import unittest
class TestType(unittest.TestCase):
def test_int_bool(self):
self.assertEqual(1, True) # Тест пройдет, но это может быть неочевидно
# Более строгая проверка: self.assertIs(1, True) упадет
if __name__ == '__main__':
unittest.main(). ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
4. Использование assertEqual для проверки на None. Хотя это работает, предпочтительнее использовать специализированный assertIs.
import unittest
def get_value():
return None
class TestNone(unittest.TestCase):
def test_none(self):
value = get_value()
self.assertEqual(value, None) # Работает
self.assertIs(value, None) # Более идиоматично и читаемо
if __name__ == '__main__':
unittest.main()Изменения в последних версиях
В основных версиях Python метод assertEqual не претерпевал значительных синтаксических изменений, так как является фундаментальным для фреймворка unittest. Однако связанные улучшения присутствуют.
Python 3.2: Добавлен метод assertNotIn и другие, расширяющие набор, но не меняющие поведение assertEqual.
Python 3.4: В сообщениях об ошибках для assertMultiLineEqual (который иногда вызывается из assertEqual для строк) улучшено отображение различий.
Python 3.11: Повышена производительность модуля unittest в целом, что косвенно касается и выполнения assertEqual. Добавлены более информативные сообщения об ошибках для некоторых типов данных.
Важно отметить, что сама логика сравнения через оператор == остается неизменной. Основные обновления касаются окружающей инфраструктуры, улучшения диагностических сообщений и производительности.
Расширенные и специализированные примеры
Сравнение сложных структур данных (словарей со вложенными списками). Метод рекурсивно сравнивает элементы.
import unittest
class TestComplexStructures(unittest.TestCase):
def test_config(self):
expected_config = {
'version': 1,
'params': {'max_users': 100, 'roles': ['admin', 'user']},
'enabled': True
}
actual_config = {
'version': 1,
'params': {'max_users': 100, 'roles': ['admin', 'user']},
'enabled': True
}
self.assertEqual(actual_config, expected_config)
if __name__ == '__main__':
unittest.main(). ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
Использование с пользовательскими классами. Для корректной работы необходимо определить метод __eq__.
import unittest
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
if not isinstance(other, Person):
return False
return self.name == other.name and self.age == other.age
class TestCustomClass(unittest.TestCase):
def test_person(self):
p1 = Person('Ivan', 30)
p2 = Person('Ivan', 30)
self.assertEqual(p1, p2) # Без __eq__ тест бы упал
if __name__ == '__main__':
unittest.main(). ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
Сравнение множеств (set). Порядок элементов не важен.
import unittest
class TestSet(unittest.TestCase):
def test_set_equality(self):
set1 = {1, 2, 3, 4}
set2 = {4, 3, 2, 1}
self.assertEqual(set1, set2) # Тест пройдет
if __name__ == '__main__':
unittest.main(). ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
Сравнение объектов datetime.
import unittest
from datetime import datetime, timezone
class TestDateTime(unittest.TestCase):
def test_datetime(self):
dt1 = datetime(2023, 10, 5, 12, 0, 0, tzinfo=timezone.utc)
dt2 = datetime(2023, 10, 5, 12, 0, 0, tzinfo=timezone.utc)
self.assertEqual(dt1, dt2)
if __name__ == '__main__':
unittest.main(). ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
Проверка возвращаемого значения функции. Самый частый сценарий использования.
import unittest
def factorial(n):
if n == 0:
return 1
return n * factorial(n - 1)
class TestFactorial(unittest.TestCase):
def test_factorial_of_zero(self):
self.assertEqual(factorial(0), 1)
def test_factorial_of_five(self):
self.assertEqual(factorial(5), 120)
if __name__ == '__main__':
unittest.main().. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK
Сравнение сгенерированных последовательностей, например, генераторов. Генератор необходимо преобразовать в список для сравнения.
import unittest
class TestGenerator(unittest.TestCase):
def test_generator(self):
gen = (x for x in range(3))
# self.assertEqual(gen, [0,1,2]) # Упадет, так как сравниваются разные типы
self.assertEqual(list(gen), [0, 1, 2]) # Корректно
if __name__ == '__main__':
unittest.main(). ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
питон unittest.TestCase.assertEqual function comments
- питон unittest.TestCase.assertEqual - аргументы и возвращаемое значение
- Функция python unittest.TestCase.assertEqual - описание
- unittest.TestCase.assertEqual - примеры
- unittest.TestCase.assertEqual - похожие методы на python
- unittest.TestCase.assertEqual на php, c#, sql, java
- unittest.TestCase.assertEqual изменения python
- Примеры unittest.TestCase.assertEqual на питон