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.
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.
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.
A skip means that you expect your test to pass only if some conditions are met, otherwise pytest should skip running the test altogether.
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__ ).
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With