-
Notifications
You must be signed in to change notification settings - Fork 1.1k
use pytest-mock to simplify and improve tests, improve test docs #468
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
Conversation
docs/sphinx/source/contributing.rst
Outdated
|
||
# did the method call the function as we expected? | ||
# mocker.spy added assert_called_once_with to the function | ||
pvsystem.ashraeiam.assert_called_once_with(thetas, b=0.05) |
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.
Here, why do we pass b=-0.05
instead of module_parameters[b]
? If b=0.05
is intended then why is module_parameters
needed? Just looking to clarify.
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.
In the example above, either b=0.05
or b=module_parameters['b']
would work. What is important is that something dict-like is passed to PVSystem
. For example, this would also work:
system = pvsystem.PVSystem(module_parameters={'b': 0.05})
followed by the assert statement as shown. Or this would work:
b = 0.05
system = pvsystem.PVSystem(module_parameters=dict(b=b))
# ...
pvsystem.ashraeiam.assert_called_once_with(thetas, b=b)
Would one of the above be a better example? Or more comments?
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.
I think it would appear more clear to me if we change line 157 to module_parameters = {'b' : 0.05}
which avoids recasting the dict as a pandas object. Also, to me it is more consistent to use the dict in the assertion, assert_called_once_with(thetas, module_parameters['b'])
instead of assert_called_once_with(thetas, b=0.05)
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.
Thanks. That makes sense.
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.
@cwhanse do you want to review this and merge if acceptable? I know I need to make one change to replace a test I accidentally removed. I'll do that next.
Use the "squash and merge" feature so that we can maintain a simple commit history. If you don't already see it, it's under the arrow button on the right side of green merge button.
@@ -21,38 +21,11 @@ | |||
|
|||
from conftest import needs_numpy_1_10, requires_scipy | |||
|
|||
latitude = 32.2 |
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.
I removed this block of code to make all of tests self-contained. A small amount of it is moved into a couple of functions. None of these changes are completely necessary for pytest-mock improvements, but I was already in "improve the tests" mode.
@@ -9,7 +9,7 @@ contribute. | |||
|
|||
|
|||
Easy ways to contribute | |||
----------------------- | |||
~~~~~~~~~~~~~~~~~~~~~~~ |
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.
I think these needed to change to make the new level of organization work below (Functions, PVsystem/Location, ModelChain).
|
||
pvlib's unit tests can easily be run by executing ``py.test`` on the | ||
pvlib directory: | ||
|
||
``py.test pvlib`` | ||
``pytest pvlib`` |
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.
Older versions of pytest were called with py.test. Now it's just pytest.
@@ -113,15 +99,14 @@ def test_ashraeiam_scalar(): | |||
assert_allclose(iam, expected, equal_nan=True) | |||
|
|||
|
|||
@needs_numpy_1_10 |
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.
numpy 1.10 is only needed for tests that use assert_allclose(equal_nan=True)
out = system.sapm_spectral_loss(airmass) | ||
|
||
|
||
@pytest.mark.parametrize("expected", [1.03173953]) |
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.
I accidentally deleted this test in a merge. I'll fix next.
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.
Added below.
pvsystem.sapm_effective_irradiance.assert_called_once_with( | ||
poa_direct, poa_diffuse, airmass_absolute, aoi, sapm_module_params, | ||
reference_irradiance=reference_irradiance) | ||
assert_allclose(out, 1, atol=0.1) |
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.
This low-precision test will fail if we change the units of effective irradiance. That could be an argument for or against having any low-precision tests at all, depending on your perspective.
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.
Here, we are testing that pvsystem.sapm_effective_irradiance
is called and returns a reasonable value, correct? If so, then I would change airmass_absolute = 1.5
, aoi = 0
and poa_direct = 900
. We should keep reference_irradiance = 1000
. With these inputs the method call should return 1.0 exactly. At least until we act on #472
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.
I updated the input parameters.
Here, we are testing that pvsystem.sapm_effective_irradiance is called and returns a reasonable value, correct?
Yes, so I kept atol=0.1
.
pvlib/test/test_pvsystem.py
Outdated
system = pvsystem.PVSystem(modules_per_string=2, strings_per_inverter=3) | ||
m = mocker.patch( | ||
'pvlib.pvsystem.scale_voltage_current_power', autospec=True) |
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.
This test function uses a different pattern than the others. Unlike mocker.spy
, mocker.patch
can only be used to test that something is called because it completely replaces the function/method under consideration. I chose this pattern here because I think the input data is a little more complicated than is worth maintaining in the method test. Could be changed, though.
pvsystem.sapm_effective_irradiance.assert_called_once_with( | ||
poa_direct, poa_diffuse, airmass_absolute, aoi, sapm_module_params, | ||
reference_irradiance=reference_irradiance) | ||
assert_allclose(out, 1, atol=0.1) |
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.
Here, we are testing that pvsystem.sapm_effective_irradiance
is called and returns a reasonable value, correct? If so, then I would change airmass_absolute = 1.5
, aoi = 0
and poa_direct = 900
. We should keep reference_irradiance = 1000
. With these inputs the method call should return 1.0 exactly. At least until we act on #472
Rewrites PVSystem tests using
pytest-mock
and adds a new ModelChain test. Please see the whatsnew diff and the new documentation for more details on how and why.The changes to
test_pvsystem.py
are complete (I think). I don't currently have time to go through the entiretest_modelchain.py
module and improve the tests to use the new methods. I suggest calling it good enough for this pull request. It at least provides an example for people working with the modelchain code in the future.See discussion in #466 in this comment and below for more context.
git diff upstream/master -u -- "*.py" | flake8 --diff
and/or landscape.io linting service.docs/sphinx/source/api.rst
for API changes.docs/sphinx/source/whatsnew
file for all changes.