Skip to content
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

parametrize part of parser test cases with pytest #727

Merged
merged 2 commits into from Jun 8, 2018

Conversation

jpurviance
Copy link
Member

@jpurviance jpurviance commented May 23, 2018

Summary of changes

@pganssle suggested that it would be good to migrate the tests to parameterized pytests.

This is a possible partial conversion.
I've tried to keep the grouping and meaning of test cases the same.

I've converted the old test function signatures to assertion messages. Where appropriate, I've integrated the comments from the test cases into the error messages as well. I've noticed that a large number of the test cases weretestSomeThing1, testSomeThing2, testSomeThing3,... where the trailing number has appeared to be indexing the i'th test case I have dropped it.

Closes

Pull Request Checklist

@@ -27,6 +27,132 @@
except ValueError:
PLATFORM_HAS_DASH_D = False

parser_test_cases = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these sorts of globals I have tended to use ALL_CAPS

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, i'm not sure how i fee about the variable name anyway. All of these tests are "parser test cases"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They don't have to go into a variable at all if you don't want.

Most of the time I just pass them directly into the parametrize decorator, like so:

@pytest.mark.parametrize('arg1, arg2', [
    (1, 2),
    (3, 4),
    (5, 6),
])
def test_func(arg1, arg2):
    assert func(arg1, arg2)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw this style of parameterization in some of the other test files. I chose against it because a lot of the important code, like: @pytest.mark.parametrize('arg1, arg2', [, is not close to the function being decorated.

I didn't like that it did not fit on one screen for both how the args are being used and what the args are. With them separated, you have to the data to be injected separate form how it is injected. I liked this because I felt the "how" should live near the function being decorated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's a reasonable choice. I would probably go with ALL_CAPS if you are going with global scope, though. See dateutil/tests/test_isoparser.py for how I did it.



@pytest.fixture
def default():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the advantage of using a fixture for this? I will admit I don't love fixtures in general because they feel too magical (being being injected by name into the arguments is... very weird).

Since all it does is provide a datetime literal, maybe just pass that to default instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pytest likes dependency injection. test_parser_default is not testing a specific default value, it is instead testing that given some text and a default that you create an expected datetime object. The test is currently written to assert that given some text an a default a particular result is created. The alternative would given some text with an exact default a particular result is created.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if we ever change default from returning this specific datetime literal, all the parametrized tests would immediately break, right? So really the test is whether that specific result is created given this specific default value. What specific things could we do with this fixture that a datetime literal don't accomplish?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this test case and your example, not much.

Things like this would be possible: https://docs.pytest.org/en/latest/fixture.html#parametrizing-fixtures

However, since that datetime object needs to be in a particular state, I don't see parametrizing fixtures useful.

@@ -536,9 +536,6 @@ def testMicrosecondPrecisionErrorReturns(self):
dt = datetime(2008, 2, 27, 21, 26, 1, ms)
self.assertEqual(parse(dt.isoformat()), dt)

# def testHighPrecisionSeconds(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... Not sure why this is commented out. If it fails it should be converted to an xfail.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be deleted in the last commit. I missed it when I removed all the commented out tests. its here as a specific commit because I cherry picked two of the commits from the previously closed pr. see: 42f62c2

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh you commented them out as you moved them over, I see.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, very scientific.

Tried to preserver comments in assertion messages. Lots of the test case names
did not have much meaning, this would be a good time to fix that.
Copy link
Member

@pganssle pganssle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I love the "assert message" stuff, because I think it overrides the normal pytest failure stuff, but we can change that later.

@pganssle pganssle merged commit 86e3351 into dateutil:master Jun 8, 2018
@pganssle pganssle added this to the Master milestone Jun 8, 2018
@jpurviance jpurviance deleted the parser_pytest branch June 11, 2018 01:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants