-
-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Django 2.0 compatibility and improved test coverage #60
base: master
Are you sure you want to change the base?
Changes from all commits
037d262
9df9301
49ab46c
a093f6f
7d77c13
5f5e3a6
9960816
6d946fc
20e9b99
9835972
ee0eeec
577fdc8
8c8a61c
4db898c
a85ee42
4bde111
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,3 +28,4 @@ cover/ | |
.cache/ | ||
htmlcov/ | ||
coverage.xml | ||
/.pytest_cache |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,9 @@ case>=1.3.1 | |
pytest>=3.0 | ||
pytest-django==3.1.2 | ||
pytz>dev | ||
|
||
# Allows freezing of current time in tests | ||
freezegun==0.3.9 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is 0.3.10, please update. |
||
|
||
# Provides unittest.mock when running the test suite on Python 2 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That comment seems wrong, the mock package doesn't provide |
||
mock==2.0.0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from __future__ import absolute_import, unicode_literals | ||
|
||
from datetime import datetime | ||
from unittest import TestCase | ||
from mock import Mock | ||
|
||
from freezegun import freeze_time | ||
|
||
from django_celery_monitor.admin import colored_state, node_state, eta,\ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use parenthesis for implied line-continuation instead of a backslash here. |
||
tstamp, name | ||
|
||
|
||
class ColoredStateTest(TestCase): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please move all the tests under a common TestCase class, e.g. |
||
def test_success(self): | ||
"""Rendering of a sucessful task's state.""" | ||
mock_task = Mock() | ||
mock_task.state = 'SUCCESS' | ||
expected_html = '<b><span style="color: green;">SUCCESS</span></b>' | ||
assert colored_state(mock_task) == expected_html | ||
|
||
|
||
class NodeStateTest(TestCase): | ||
def test_online(self): | ||
"""Rendering of an online node's state.""" | ||
mock_node = Mock() | ||
mock_node.is_alive.return_value = True | ||
expected_html = '<b><span style="color: green;">ONLINE</span></b>' | ||
assert node_state(mock_node) == expected_html | ||
|
||
|
||
class ETATest(TestCase): | ||
def test_eta_value_not_set(self): | ||
"""Rendering when no ETA is specified by the task.""" | ||
mock_task = Mock() | ||
mock_task.eta = None | ||
expected_html = '<span style="color: gray;">none</span>' | ||
assert eta(mock_task) == expected_html | ||
|
||
def test_eta_value_set(self): | ||
"""Rendering when an ETA value is set by the task.""" | ||
mock_task = Mock() | ||
mock_task.eta = datetime(2020, 1, 2, 8, 35) | ||
expected_html = '2020-01-02 08:35:00+00:00' | ||
assert eta(mock_task) == expected_html | ||
|
||
|
||
class TStampTest(TestCase): | ||
def test_time_difference_of_roughly_two_years(self): | ||
"""Timestamp is roughly two years into the past.""" | ||
mock_task = Mock() | ||
mock_task.tstamp = datetime(2015, 8, 5, 17, 3) | ||
expected_html = '<div title="2015-08-05 17:03:00+00:00">2 years ago' \ | ||
'</div>' | ||
with freeze_time(datetime(2017, 8, 6)): | ||
assert tstamp(mock_task) == expected_html | ||
|
||
|
||
class NameTest(TestCase): | ||
def test_no_more_than_16_characters(self): | ||
""" | ||
No truncation should happen on names that are at most 16 characters in | ||
length. | ||
""" | ||
mock_task = Mock() | ||
mock_task.name = '1234567890123456' | ||
expected_html = '<div title="1234567890123456"><b>1234567890123456' \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't use backslashes for line continuation. |
||
'</b></div>' | ||
assert name(mock_task) == expected_html | ||
|
||
def test_more_than_16_characters(self): | ||
"""Truncation should happen above 16 characters.""" | ||
mock_task = Mock() | ||
mock_task.name = '12345678901234567' | ||
expected_html = '<div title="12345678901234567"><b>123456789012345' \ | ||
'…</b></div>' | ||
assert name(mock_task) == expected_html |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from __future__ import absolute_import, unicode_literals | ||
|
||
from re import match | ||
from unittest import TestCase | ||
|
||
from mock import Mock | ||
|
||
from django_celery_monitor.utils import fixedwidth | ||
|
||
|
||
class FixedWidthTest(TestCase): | ||
def test_unpretty_string(self): | ||
"""Do not request pretty printing for a string.""" | ||
task_mock = Mock() | ||
task_mock.name = 'testing' | ||
expected_html = '<span title="testing" style="font-size: 6pt; font-' \ | ||
'family: Menlo, Courier; ">testing</span> ' | ||
assert fixedwidth('name')(task_mock) == expected_html | ||
|
||
def test_pretty_string(self): | ||
"""Request pretty printed value for a string.""" | ||
task_mock = Mock() | ||
task_mock.name = 'testing' | ||
expected_html = ('<span title="testing" style="font-size:' | ||
' 6pt; font-family: Menlo, Courier; ">testing' | ||
'</span> ') | ||
assert fixedwidth('name', pretty=True)(task_mock) == expected_html | ||
|
||
def test_pretty_object(self): | ||
"""Request pretty printed value for an object.""" | ||
task_mock = Mock() | ||
task_mock.name = object() | ||
actual_html = fixedwidth('name', pretty=True)(task_mock) | ||
matcher = match( | ||
'<span title="<object object at 0x[0-9a-f]+>" style="' | ||
'font-size: 6pt; font-family: Menlo, Courier; ">' | ||
'<object object at 0x[0-9a-f]+></span> ', | ||
actual_html, | ||
) | ||
assert matcher |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
[tox] | ||
envlist = | ||
tests-py{py,27,34,35}-dj{18,19,110} | ||
tests-py36-dj111 | ||
tests-py{27,35,36}-dj111 | ||
tests-py{35,36}-dj20 | ||
apicheck | ||
builddocs | ||
flake8 | ||
|
@@ -24,10 +24,8 @@ deps= | |
-r{toxinidir}/requirements/test.txt | ||
-r{toxinidir}/requirements/test-ci.txt | ||
|
||
dj18: django>=1.8,<1.9 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't remove 1.8, 1.9. and 1.10 yet. |
||
dj19: django>=1.9,<1.10 | ||
dj110: django>=1.10,<1.11 | ||
dj111: django>=1.11,<2 | ||
dj20: django>=2.0,<2.1 | ||
|
||
apicheck,builddocs,linkcheck: -r{toxinidir}/requirements/docs.txt | ||
flake8,flakeplus,manifest,pydocstyle,readme: -r{toxinidir}/requirements/pkgutils.txt | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please continue to use
abbrtask
here since it does more than what this code does. Just cutting off the task name would make identifiying a task with a long import path hard to read.E.g. Imagine a task with the name
myproject.some_complex_app.under_module.tasks.version_2.whatever_task
(something that I've seen myself). In that case I wouldn't even see the task name with this new code. Insteadabbrtask
will show[.]whatever_task
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although I'm sympathetic to your concerns about the way it abbreviates names, sticking with
abbrtask
from Celery simply didn't seem like an option.The
abbrtask
function from Celery doesn't actually do what the docstring of thename
function promises. It doesn't cut off at the requested amount of characters. So when I wrote unit tests for thename
function, I found behavior that contradicts promises made in the docstring.I had to choose between:
abbrtask
function but doing postprocessing on it as a workaroundabbrtask
functionI went for option 3. Would you make a different choice?