Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ignore a warning inside a test using pytest?

I am trying to test a function that uses DatetimeFields. The function I want to test is the following:

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

I am using pytest for testing, so the test that I have implemented is the following:

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

The tests passes, but the problem is that I am getting the following warning:

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

Actually, I get several RuntimeWarning which notify the use of a naive datetime while time zone support is active.

How can I disable warnings just for this test? I found that using @pytest.mark.filterwarnings might be useful, and I have added the tag as this: @pytest.mark.filterwarnings('ignore:RuntimeWarning'). However, that didn't work, and after running the test I still have those warnings.

Does the order of where I put the decorator matters? I have tried several combinations, but it does't work yet.

In the documentation I found that I can add addopts = -p no:warnings to my pytest.ini file, but I don't want to follow this approach in case I get another test generating this warning.

like image 844
lmiguelvargasf Avatar asked Apr 01 '18 16:04

lmiguelvargasf


People also ask

How do I ignore warnings in pytest?

Use warnings. filterwarnings() to ignore deprecation warnings Call warnings. filterwarnings(action, category=DeprecationWarning) with action as "ignore" and category set to DeprecationWarning to ignore any deprecation warnings that may rise.

How do I ignore a warning in Python?

Suppress Specific Warnings In PythonUse the 'filterwarnings()' function to ignore all warnings by setting 'ignore' as a parameter. In addition to that, add a parameter 'category' and specify the type of warning.

What does pytest Mark skip do?

A skip means that you expect your test to pass only if some conditions are met, otherwise pytest should skip running the test altogether.

What is DeprecationWarning in Python?

DeprecationWarning. Base category for warnings about deprecated features when those warnings are intended for other Python developers (ignored by default, unless triggered by code in __main__ ).


1 Answers

According to pytest documentation, @pytest.mark.filterwarnings actually is the right approach, the problem was that the parameter that I was passing was not correct. This issue was solved by:

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

so the test works as follows:

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
like image 149
lmiguelvargasf Avatar answered Oct 10 '22 08:10

lmiguelvargasf