[MRG] Refactor test_disk.py as per pytest design.#446
Conversation
|
conftest.py will grow over time, probably we may end up emptying up joblib/test/common.py as well, if need be.. |
|
@lesteve Please review this code whenever you feel convenient 😄 |
joblib/test/test_disk.py
Outdated
| ('1.4M', int(1.4 * 1024 ** 2), None), | ||
| ('120M', 120 * 1024 ** 2, None), | ||
| ('53K', 53 * 1024, None), | ||
| ('fooG', None, ValueError)]) |
There was a problem hiding this comment.
Put the exception in a separate test function this way test_mem_str_to_bytes can be simpler.
joblib/testing.py
Outdated
| assert_equal = _dummy.assertEqual | ||
| assert_not_equal = _dummy.assertNotEqual | ||
| assert_raises = _dummy.assertRaises | ||
| assert_raises = pytest.raises |
There was a problem hiding this comment.
I think I said somewhere else that I would have a different name to make it clear that it is not the stldlib assert_raises, maybe pytest_assert_raises.
There was a problem hiding this comment.
Is there an advantage of using pytest.raises in the tests affected by this PR?
For the record, my personal preference is to always use assert_raises_regex in order to check the error message. I have seen cases where the test pass but the exception is raised for a completely different reason.
pytest has some way with a context manager of checking the error message by the way.
There was a problem hiding this comment.
pytest has some way with a context manager of checking the error message by the way.
Yeah quite convenient, have a look
joblib/test/conftest.py
Outdated
| from joblib.testing import fixture | ||
|
|
||
|
|
||
| @fixture(scope='function') |
There was a problem hiding this comment.
Just checking we don't actually need to write a fixture, provided we use tmpdir as the test function arguments and tmpdir.strpath in the test function body right?
Maybe this solution would have my preference.
There was a problem hiding this comment.
Sure, I was fine the either way, although at one point I thought tmpdir.strpath would be a bit clumsy everywhere.
There was a problem hiding this comment.
I think what this is is me, as a new pytest user, being a bit wary about pytest magic ... Leave it like this is fine.
joblib/test/test_disk.py
Outdated
| mkdirp(os.path.join(tmpdir_path, 'ham')) | ||
| mkdirp(os.path.join(tmpdir_path, 'ham')) | ||
| mkdirp(os.path.join(tmpdir_path, 'spam', 'spam')) | ||
| @parametrize(['text', 'exception', 'exc_substr'], |
There was a problem hiding this comment.
You don't need the parametrize here anymore, right?
There was a problem hiding this comment.
I mean you are parametrizing over one item so there is no need to parametrize and you can use local variables into a standard test function.
There was a problem hiding this comment.
Please refer this thread Coincidentially we wrote our comments at the same moment 😄
joblib/test/test_disk.py
Outdated
| def test_memstr_to_bytes_exception(text, exception, exc_substr): | ||
| with pytest_assert_raises(exception) as excinfo: | ||
| memstr_to_bytes(text) | ||
| assert exc_substr in str(excinfo.value) |
There was a problem hiding this comment.
The "pytest" way of assert_raises_regex. Also there's just one test case but it looks better this way in my opinion.
There was a problem hiding this comment.
You don't need the parametrize here anymore, right?
@lesteve I was writing this comment simultaneously, well in variable names exception, text and exc_substr make the test body very generic. I chose to write it this way because of the way the method just above this was written in a similar manner. No objections in modifying it though, shall I ?
There was a problem hiding this comment.
Also, looking at the code of memstr_to_bytes it looks like the ValueError can be raised both by a prior KeyError as well as a ValueError. Maybe a good time to test it properly by corresponding two test cases ? Or is it not that significant ?
joblib/test/test_disk.py
Outdated
| def test_memstr_to_bytes_exception(text, exception, exc_substr): | ||
| with pytest_assert_raises(exception) as excinfo: | ||
| memstr_to_bytes(text) | ||
| assert exc_substr in str(excinfo.value) |
There was a problem hiding this comment.
You can use excinfo.match(r'.* 123 .*') according to http://doc.pytest.org/en/latest/assert.html. It is general a good idea to make sure that the value the user provided is given in the error message. Here you could check 'Invalid literal for size.*fooG'.
dfad634 to
991e36d
Compare
991e36d to
d3cae30
Compare
|
|
||
| @parametrize(['text', 'exception', 'regex'], | ||
| [('fooG', ValueError, r'Invalid literal for size.*fooG.*'), | ||
| ('1.4N', ValueError, r'Invalid literal for size.*1.4N.*')]) |
There was a problem hiding this comment.
try:
size = int(units[text[-1]] * float(text[:-1]))
except (KeyError, ValueError):
raise ValueError(
"Invalid literal for size give: %s (type %s) should be "
"alike '10G', '500M', '50K'." % (text, type(text)))So to test this block of memstr_to_bytes I added one more test case. First case causes ValueError before landing in except block while second causes KeyError.
There was a problem hiding this comment.
I can tell you were just looking for an excuse to keep the parametrize ;-).
There was a problem hiding this comment.
Haha you got me xD anyways jokes apart, I can revert back if you wish..
|
@lesteve The failing job on Travis CI uses |
The reason for that is that conda has some dependency constraints that are not up-to-date for python 3.3. Pytest 3 works perfectly well with python 3.3 AFAIK. I am going to install pytest via pip and that should fix this problem. |
to make sure we have a pytest version >=3 even on Python 3.3
|
Side note we will probably drop support for Python 3.3 in the not too distant future. |
Yes you are correct, pytest works fine with python 3.3. I was puzzled by the fact that always
Yeah that fixed it, great ! Thanks for the help 😄 |
|
OK merging this one, thanks a lot! Feel free to reintroduce the tmpdir_path fixture in conftest.py in your next PR. |
|
Great, thanks for the continuous review feedbacks ! As usual, next PR on the way... |
|
Thanks Karan, it's great to have you on board.
|
Third Phase PR on #411 (Succeeding PR #441)
This PR deals with refactor of tests in test_disk.py to adopt the pytest flavor.
assert_raisesnow derived from pytest because it removes two redundant layers from traceback. In a deliberately created failure,pytest.raisesonly highlights the last two lines in this traceback as opposed to unittests traceback (the complete one)...