Примеры сравнения чисел с плавающей точкой в pytest

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Простейшим способом утверждения приближенного равенства чисел с плавающей точкой в pytest служит функция pytest.approx().

Пример:

Python
Скопировать код
assert 0.1 * 3 == pytest.approx(0.3)

Также возможно отрегулировать уровень точности через параметры abs или rel.

Пример с настройкой точности:

Python
Скопировать код
assert 0.1 * 3 == pytest.approx(0.3, abs=1e-12)

В дальнейшем углубимся в более сложные случаи и обсудим другие доступные для этого инструменты.

Кинга Идем в IT: пошаговый план для смены профессии

Первый уровень сложности: pytest для сложных задоч

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

Сравнение переполненных кортежей

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

Python
Скопировать код
assert all(map(lambda x, y: abs(x – y) < threshold, tuple1, tuple2))
# Здесь надо быть бездушным — всё или ничего

Указанный код последовательно сравнивает элементы кортежей, обеспечивая ясность и эффективность тестов.

Альтернативы с NumPy и Unittest

Если вы предпочитаете работать с библиотеками NumPy или unittest, именно они предлагают отличные способы для утверждения приближенного равенства чисел с плавающей точкой.

NumPy's assert_allclose:

Python
Скопировать код
import numpy as np

np.testing.assert_allclose(actual_array, expected_array, rtol=1e-5)
# Отлично подходит не только для задач с числами с плавающей точкой, но и для метания подков.

Unittest's assertAlmostEqual:

Python
Скопировать код
import unittest

class TestFloats(unittest.TestCase):
    def test_floats(self):
        self.assertAlmostEqual(0.1 * 3, 0.3, places=5)
        # Работа со сравнением чисел с плавающей точкой напоминает: нужно быть готовым к малым неточностям.

Больше гибкости с пользовательской функцией

Создание собственной функции может дать дополнительную гибкость и адаптацию к конкретным кейсам.

Python
Скопировать код
def are_floats_almost_equal(x, y, tolerance):
    return abs(x – y) < tolerance

assert are_floats_almost_equal(0.1 * 3, 0.3, 1e-12)
# Готов потерпеть что угодно, кроме нетерпимости... и значительных погрешностей в числах с плавающей точкой.

Высокая точность благодаря math.isclose()

Ваши усилия по написанию прозрачного кода не приведут к ущербу для его точности, если вы используете math.isclose() в Python:

Python
Скопировать код
import math

assert math.isclose(0.1 * 3, 0.3, rel_tol=1e-9)
# Мы ближе, чем может показаться на первый взгляд.

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

Визуализация

Следующая визуализация поможет лучше понять, как работает утверждение приближенного равенства в pytest:

Markdown
Скопировать код
Цель 🎯: это 'точное значение', к которому мы стремимся
Стрела 1 🏹: Результат, близкий к цели
Стрела 2 🏹: Результат, весьма отклонившийся от цели

                    🎯
                \  |  /
                – 🏹 -
                /  |  \

pytest позволяет засчитать попадание стрелы 1 🏹 как почти точное при малых погрешностях.

Python
Скопировать код
assert actual_value == pytest.approx(expected_value, abs=tolerance)

Яблочко: expected_value Круг допустимого отклонения: tolerance Стрела 1: actual_value, попадающий в пределы допустимой погрешности Стрела 2: выход за пределы допустимой погрешности, соответственно ошибка утверждения

Обучение на ошибках

Использование сообщений об ошибках в утверждениях значительно упрощает отладку:

Python
Скопировать код
assert a == pytest.approx(b), f"Ожидалось {b}, получено {a}"
# Ого! Похоже, что-то пошло не так.

Такие сообщения предоставляют важные сведения об ошибках и ускоряют процесс отладки.

Полезные материалы

  1. API Reference — документация pytest — официальная документация pytest, раскрывающая использование approx для утверждений приближенного равенства.
  2. numpy.testing.assert_almost_equal — Руководство NumPy v1.26 — справка по сравнению массивов с учетом допустимых отклонений от стандартов с применением NumPy.
  3. [pytest Quick Start Guide [Книга]](https://www.oreilly.com/library/view/pytest-quick-start/9781789347562/) — краткое введение в утверждения и плагины в pytest для новичков.
  4. Эффективное тестирование с помощью pytest – Real Python — подробное руководство по тестированию на базе pytest для разработчиков на Python.
  5. unittest — Фреймворк модульного тестирования — Документация Python 3.12.2 — методы утверждения приближенного равенства в unittest.
  6. Тестирование Python с помощью pytest: Просто, быстро, эффективно и масштабируемо, автор Brian Okken — практические стратегии для тестирования в Python с использованием pytest.
  7. The Floating-Point Guide – Сравнение — обзор распространенных проблем при сравнении чисел с плавающей точкой и их решений.