Как использовать `assertEqual ()` [или эквивалентный] без особого багажа? - PullRequest
0 голосов
/ 20 октября 2018

Я ищу метод (если доступен), который может сравнивать два значения и выдавать ошибку подтверждения со значимым сообщением при сбое сравнения.

Если я использую assert, сообщение об ошибке несодержать, какие значения сравнивались при неудачном утверждении.

>>> a = 3
>>> b = 4
>>> assert a == b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
>>> 

Если я использую метод assertEqual() из пакета unittest.TestCase, сообщение подтверждения содержит сравниваемые значения.

        a = 3
        b = 4
>       self.assertEqual(a, b)
E       AssertionError: 3 != 4

Обратите внимание, что здесь сообщение об ошибке подтверждения содержит сравниваемые значения.Это очень полезно в реальных сценариях и, следовательно, необходимо для меня.Простой assert (см. Выше) этого не делает.

Однако до сих пор я мог использовать assertEqual() только в классе, который наследуется от unittest.TestCase и предоставляет несколько других необходимых методов, таких как runTest().Я хочу использовать assertEqual() где угодно, а не только в унаследованных классах.Это возможно?

Я попробовал следующее, но они не работали.

>>> import unittest
>>> unittest.TestCase.assertEqual(a, b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method failUnlessEqual() must be called with TestCase instance as first argument (got int instance instead)
>>> 
>>> 
>>> tc = unittest.TestCase()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/unittest.py", line 215, in __init__
    (self.__class__, methodName)
ValueError: no such test method in <class 'unittest.TestCase'>: runTest
>>> 

Есть ли какой-либо другой пакет или библиотека, которая предлагает подобные методы, такие как assertEqual(), которые можно легко использовать без дополнительных ограничений?

Ответы [ 5 ]

0 голосов
/ 22 мая 2019

Метод assertEqual или любой другой метод assertXxx () ожидает, что первый аргумент будет ссылкой на объект.Обычно мы называем метод как self.assertEqual(first, second, msg=None).Здесь self удовлетворяет первому ожидаемому аргументу.Чтобы обойти эту ситуацию, мы можем сделать следующее:

from unittest import TestCase as tc
def some_func():
    dummy_obj = tc()
    tc.assertEqual(dummy_obj, 123, 123, msg='Not Equal')

Причиной такого поведения является Hangover из сред XUnit.

0 голосов
/ 20 октября 2018

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

import inspect

def custom_assert(condition):
    if not condition:
        frame = inspect.currentframe()
        frame = inspect.getouterframes(frame)[1]
        call_signature = inspect.getframeinfo(frame[0]).code_context[0].strip()

        import re
        argument = re.search('\((.+)\)', call_signature).group(1)
        if '!=' in argument:
            argument = argument.replace('!=','==')
        elif '==' in argument:
            argument = argument.replace('==','!=')
        elif '<' in argument:
            argument = argument.replace('<','>=')
        elif '>' in argument:
            argument = argument.replace('>','<=')
        elif '>=' in argument:
            argument = argument.replace('>=','<')
        elif '<=' in argument:
            argument = argument.replace('<=','>')

        raise AssertionError(argument)

if __name__ == '__main__':
    custom_assert(2 == 1)

Вывод:

Traceback (most recent call last):
  File "custom_assert.py", line 27, in <module>
    custom_assert(2 == 1)
  File "custom_assert.py", line 24, in custom_assert
    raise AssertionError(argument)
AssertionError: 2 != 1
0 голосов
/ 20 октября 2018

вы смотрели на numpy.testing?

https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.testing.html

Среди прочего он имеет: assert_almost_equal (фактическое, желаемое [, ...]) Вызывает ошибку AssertionError, если два элемента не равны с требуемой точностью.

Это утверждение печатает фактическое и желаемое.Если вы повысите точность, сравнение будет произвольно близко к == (для значений с плавающей запятой)

0 голосов
/ 20 октября 2018

Можно создать «вспомогательный» новый модуль, обеспечивающий доступ к функциям assert.AssertsAccessor в этом случае:

from unittest import TestCase

# Dummy TestCase instance, so we can initialize an instance
# and access the assert instance methods
class DummyTestCase(TestCase):
    def __init__(self):
        super(DummyTestCase, self).__init__('_dummy')

    def _dummy(self):
        pass

# A metaclass that makes __getattr__ static
class AssertsAccessorType(type):
    dummy = DummyTestCase()

    def __getattr__(cls, key):
        return getattr(AssertsAccessor.dummy, key)

# The actual accessor, a static class, that redirect the asserts
class AssertsAccessor(object):
    __metaclass__ = AssertsAccessorType

Модуль необходимо создать только один раз, и тогда все утверждения из пакета unittest доступны, например:

AssertsAccessor.assertEquals(1, 2)

AssertionError: 1! = 2

Или другой пример:

AssertsAccessor.assertGreater(1, 2)

Что приводит к:

AssertionError:1 не более 2

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

from assertions import AssertsAccessor

def foo(small_arg, big_arg):
    AssertsAccessor.assertGreater(big_arg, small_arg)
    # some logic here
0 голосов
/ 20 октября 2018

Вы должны передать сообщение с подтверждением от руки:

assert a == b, '%s != %s' % (a, b)
# AssertionError: 3 != 4
...