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

How to ignore a warning inside a test using 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

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

RuntimeWarning: DateTimeField Pledge.timestamp received a naive datetime (2018-03-29 00:00:00) while time zone support is active.

实际上,我收到了几个 RuntimeWarning 通知在时区支持处于活动状态时使用原始日期时间。

我如何才能禁用此测试的警告?我发现使用 @pytest.mark.filterwarnings 可能会有用,我添加了这样的标签:@pytest.mark.filterwarnings('ignore:RuntimeWarning')。但是,那没有用,在 运行 测试之后我仍然有那些警告。

我放置装饰器的顺序重要吗?试了好几种组合,还是不行。

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

根据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