如何使用pytest忽略测试中的警告?

时间:2018-04-01 16:50:08

标签: python testing warnings decorator pytest

我正在尝试测试使用DatetimeFields的函数。我想测试的功能如下:

def get_pledge_frequency(last_week_pledges):
    """Returns two lists:
    pledge_frequency: containing the number of pledges per day of the last week
    weekdays: containing a letter that represents the day
    It assumes that last_week_pledges are pledges made within the last week.
    """
    pledge_frequency = []
    weekdays = []

    if last_week_pledges:
        last_7_days = [timezone.now() - timedelta(days=i) for i in range(7)]
        last_7_days.reverse()
        day_names = 'MTWTFSS'

        for day in last_7_days:
            pledge_frequency.append(
                last_week_pledges.filter(timestamp__date=day).count())
            weekdays.append(day_names[day.weekday()])

    return pledge_frequency, weekdays

我正在使用pytest进行测试,因此我实施的测试如下:

pledge_frequency_ids = ['no_pledges', 'one_pledge_today',
                        'one_pledge_not_today', 'two_pledges_same_day',
                        'two_pledges_not_same_day', 'multiple_pledges_a',
                        'multiple_pledges_b']

pledge_data = [
    ('2018-03-30', [], ([], [])),
    ('2018-03-30', ['2018-03-30'], ([0] * 6 + [1], 'SSMTWTF')),
    ('2018-03-30', ['2018-03-27'], ([0, 0, 0, 1, 0, 0, 0], 'SSMTWTF')),
    ('2018-03-31', ['2018-03-29', '2018-03-29'], ([0, 0, 0, 0, 2, 0, 0], 'SMTWTFS')),
    ('2018-03-28', ['2018-03-26', '2018-03-28'], ([0, 0, 0, 0, 1, 0, 1], 'TFSSMTW')),
    ('2018-04-01', ['2018-03-26', '2018-03-26', '2018-03-27', '2018-03-28'], ([2, 1, 1, 0, 0, 0, 0], 'MTWTFSS',)),
    ('2018-03-29', ['2018-03-25', '2018-03-26', '2018-03-27', '2018-03-28'], ([0, 0, 1, 1, 1, 1, 0], 'FSSMTWT'))]

@pytest.mark.parametrize('today, pledge_information, pledge_frequency',
                         pledge_data, ids=pledge_frequency_ids)
@pytest.mark.django_db
@mock.patch('django.utils.timezone.now')
@mock.patch('pledges.models.Pledge')
def test_get_pledge_frequency(_, mock_now, social_user, today,
                              pledge_information, pledge_frequency):
    """Tests to verify correctness of get_pledge_frequency() function.
    Covering the following cases:
    * No pledges
    * One pledge today
    * One pledge not today
    * Two pledges the same day
    * Two pledges not the same day
    * Multiple pledges particular case 0
    * Multiple pledges particular case 1"""
    mock_now.return_value = timezone.datetime.strptime(today, '%Y-%m-%d')
    for pledge_info in pledge_information:
        pledge = Pledge()
        pledge.user = social_user
        pledge.save()
        pledge.timestamp = timezone.datetime.strptime(pledge_info, '%Y-%m-%d')
        pledge.save()

    last_week_pledges = Pledge.objects.all()
    expected_frequency, expected_weekdays = pledge_frequency
    expected_weekdays = list(expected_weekdays)
    actual_frequency, actual_weekdays = get_pledge_frequency(last_week_pledges)

    assert expected_frequency == actual_frequency
    assert expected_weekdays == actual_weekdays

测试通过,但问题是我收到以下警告:

  

运行时警告:DateTimeField Pledge.timestamp在时区支持处于活动状态时收到了一个天真的日期时间(2018-03-29 00:00:00)。

实际上,我得到了几个RuntimeWarning,它们会在时区支持处于活动状态时通知使用天真的日期时间。

如何为此测试禁用警告?我发现使用@pytest.mark.filterwarnings可能很有用,我已将标记添加为:@pytest.mark.filterwarnings('ignore:RuntimeWarning')。但是,这不起作用,运行测试后我仍然有这些警告。

装饰器的位置顺序是否重要?我尝试了几种组合,但它还没有用。

在文档中,我发现我可以将addopts = -p no:warnings添加到我的pytest.ini文件中,但如果我得到另一个生成此警告的测试,我不想采用这种方法。

1 个答案:

答案 0 :(得分:6)

根据pytest documentation@pytest.mark.filterwarnings实际上是正确的方法,问题是我传递的参数不正确。这个问题通过以下方式解决:

@pytest.mark.filterwarnings('ignore::RuntimeWarning') # notice the ::

所以测试的工作原理如下:

pledge_frequency_ids = ['no_pledges', 'one_pledge_today',
                        'one_pledge_not_today', 'two_pledges_same_day',
                        'two_pledges_not_same_day', 'multiple_pledges_a',
                        'multiple_pledges_b']

pledge_data = [
    ('2018-03-30', [], ([], [])),
    ('2018-03-30', ['2018-03-30'], ([0] * 6 + [1], 'SSMTWTF')),
    ('2018-03-30', ['2018-03-27'], ([0, 0, 0, 1, 0, 0, 0], 'SSMTWTF')),
    ('2018-03-31', ['2018-03-29', '2018-03-29'], ([0, 0, 0, 0, 2, 0, 0], 'SMTWTFS')),
    ('2018-03-28', ['2018-03-26', '2018-03-28'], ([0, 0, 0, 0, 1, 0, 1], 'TFSSMTW')),
    ('2018-04-01', ['2018-03-26', '2018-03-26', '2018-03-27', '2018-03-28'], ([2, 1, 1, 0, 0, 0, 0], 'MTWTFSS',)),
    ('2018-03-29', ['2018-03-25', '2018-03-26', '2018-03-27', '2018-03-28'], ([0, 0, 1, 1, 1, 1, 0], 'FSSMTWT'))]

@pytest.mark.parametrize('today, pledge_information, pledge_frequency',
                         pledge_data, ids=pledge_frequency_ids)
@pytest.mark.filterwarnings('ignore::RuntimeWarning')
@pytest.mark.django_db
@mock.patch('django.utils.timezone.now')
@mock.patch('pledges.models.Pledge')
def test_get_pledge_frequency(_, mock_now, social_user, today,
                              pledge_information, pledge_frequency):
    """Tests to verify correctness of get_pledge_frequency() function.
    Covering the following cases:
    * No pledges
    * One pledge today
    * One pledge not today
    * Two pledges the same day
    * Two pledges not the same day
    * Multiple pledges particular case 0
    * Multiple pledges particular case 1"""
    mock_now.return_value = timezone.datetime.strptime(today, '%Y-%m-%d')
    for pledge_info in pledge_information:
        pledge = Pledge()
        pledge.user = social_user
        pledge.save()
        pledge.timestamp = timezone.datetime.strptime(pledge_info, '%Y-%m-%d')
        pledge.save()

    last_week_pledges = Pledge.objects.all()
    expected_frequency, expected_weekdays = pledge_frequency
    expected_weekdays = list(expected_weekdays)
    actual_frequency, actual_weekdays = get_pledge_frequency(last_week_pledges)

    assert expected_frequency == actual_frequency
    assert expected_weekdays == actual_weekdays