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

[OpRefactor] Do not loop over all ops in tests #1895

Merged
merged 11 commits into from Nov 16, 2021

Conversation

mariaschuld
Copy link
Contributor

@mariaschuld mariaschuld commented Nov 15, 2021

Context:

We want to delete the static num_params and num_wires attributes of operations, since in many cases these are ill-defined before instantiation. With this change, we cannot import operator classes, infer their arguments (which becomes less and less trivial anyways) and use them in tests, as is often done.

However, many of these tests should not loop automatically over operations anyways - the operations should be well-unit-tested, and outside logic should be tested with a few sample operations.

Description of the Change:

Rewrites or deletes tests where we loop blindly over operations.

Benefits:

Better test. Unblocks operator refactor.

Possible Drawbacks:

I may not have caught all cases, but I worked with the list of issues that arose from the PRs that this one is supposed to unblock!

Related GitHub Issues:

@github-actions
Copy link
Contributor

Hello. You may have forgotten to update the changelog!
Please edit doc/releases/changelog-dev.md with:

  • A one-to-two sentence description of the change. You may include a small working example for new features.
  • A link back to this PR.
  • Your name (or GitHub username) in the contributors section.

qml.DoubleExcitationPlus,
qml.DoubleExcitationMinus,
qml.OrbitalRotation,
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was funny: the logic above leaves analytic_qubit_ops with only 2-3 operations anyways :)

Copy link
Member

Choose a reason for hiding this comment

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

lmao 🤣

qml.OrbitalRotation,
}

@pytest.mark.parametrize("obs", [qml.PauliX, qml.PauliY])
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I only test with one obs, the other should work in the same way!

@codecov
Copy link

codecov bot commented Nov 15, 2021

Codecov Report

Merging #1895 (468a47c) into master (590704b) will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #1895   +/-   ##
=======================================
  Coverage   98.98%   98.98%           
=======================================
  Files         219      219           
  Lines       16512    16512           
=======================================
  Hits        16344    16344           
  Misses        168      168           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 590704b...468a47c. Read the comment docs.

@@ -788,57 +788,3 @@ def circuit():
):
circuit()
assert dev.shots == sum(shots)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Deleted this one, because we have a test_apply that should test the same thing on a lower level.

assert gaussian_dev._state[0] == pytest.approx(expected_out[0], abs=tol)
assert gaussian_dev._state[1] == pytest.approx(expected_out[1], abs=tol)
gaussian_dev = qml.device("default.gaussian", wires=1)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My thinking is this: if the apply function works, then the principle works. So I am trying it out with a constant dummy gate implementation that only transforms the covariance matrix.

Below I add more tests for gates that use forked logic in the apply function.

Copy link
Member

Choose a reason for hiding this comment

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

yes! If this is a unit test testing the apply method, we only should be checking that apply is doing as needed. There is no need to test every supported gate through apply.

@@ -894,31 +894,21 @@ def circuit(*x):
x = np.random.random([op.num_params])
circuit(*x)

@pytest.mark.parametrize("observable", set(qml.ops.cv.obs))
def test_unsupported_observable_error(self, rep, observable):
def test_unsupported_observable_error(self, rep):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is another bad pattern: to test an error message we looped over a big list of operations that produce the error, instead of one! (Same above)

Copy link
Member

Choose a reason for hiding this comment

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

so much cleaner!

@mariaschuld
Copy link
Contributor Author

This is very strange, there are circuit drawer tests failing that I never touched...

Copy link
Member

@josh146 josh146 left a comment

Choose a reason for hiding this comment

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

I think this is one of my favourite PRs to review of all time. No suggestions! I love it!

Comment on lines +17 to +19
* Tests do not loop over automatically imported and instantiated operations any more,
which was opaque and created unnecessarily many tests.
[(#1895)](https://github.com/PennyLaneAI/pennylane/pull/1895)
Copy link
Member

Choose a reason for hiding this comment

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

🙌

Comment on lines 881 to +885
with pytest.raises(
qml._device.DeviceError,
match="not supported on device default.tensor",
):
x = np.random.random([op.num_params])
circuit(*x)
circuit()
Copy link
Member

Choose a reason for hiding this comment

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

this makes so much more sense 💯

@@ -894,31 +894,21 @@ def circuit(*x):
x = np.random.random([op.num_params])
circuit(*x)

@pytest.mark.parametrize("observable", set(qml.ops.cv.obs))
def test_unsupported_observable_error(self, rep, observable):
def test_unsupported_observable_error(self, rep):
Copy link
Member

Choose a reason for hiding this comment

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

so much cleaner!

assert gaussian_dev._state[0] == pytest.approx(expected_out[0], abs=tol)
assert gaussian_dev._state[1] == pytest.approx(expected_out[1], abs=tol)
gaussian_dev = qml.device("default.gaussian", wires=1)

Copy link
Member

Choose a reason for hiding this comment

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

yes! If this is a unit test testing the apply method, we only should be checking that apply is doing as needed. There is no need to test every supported gate through apply.

qml.DoubleExcitationPlus,
qml.DoubleExcitationMinus,
qml.OrbitalRotation,
}
Copy link
Member

Choose a reason for hiding this comment

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

lmao 🤣

@mariaschuld mariaschuld merged commit 534de0a into master Nov 16, 2021
@mariaschuld mariaschuld deleted the rewrite-tests-that-loop-over-ops branch November 16, 2021 13:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants