Skip to content

Commit

Permalink
Make test ordering and parametrization reproducible (quantumlib#4788)
Browse files Browse the repository at this point in the history
Implement deterministic ordering of pytest parameters.
Add CIRQ_TESTING_RANDOM_SEED environment variable for seeding
random numbers generation in random and numpy.random modules.
Use commit epoch time as the default seed to have a non-constant,
but deterministic seeding.

NB: Use empty CIRQ_TESTING_RANDOM_SEED to prevent seeding, for example,
    CIRQ_TESTING_RANDOM_SEED="" check/pytest

This implements quantumlib#4787
  • Loading branch information
pavoljuhas authored and MichaelBroughton committed Jan 22, 2022
1 parent a8d3cde commit 0824992
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 12 deletions.
3 changes: 3 additions & 0 deletions check/pytest
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ if [ "$PYTHON_VERSION" -lt "37" ]; then
PYTEST_ARGS+=("--ignore=cirq-rigetti")
fi

: ${CIRQ_TESTING_RANDOM_SEED=$(git log -1 --pretty="%ct")}
export CIRQ_TESTING_RANDOM_SEED

if [ -z "${ACTUALLY_QUIET}" ]; then
pytest "${PYTEST_ARGS[@]}"
RESULT=$?
Expand Down
3 changes: 3 additions & 0 deletions check/pytest-changed-files
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,7 @@ fi

source dev_tools/pypath

: ${CIRQ_TESTING_RANDOM_SEED=$(git log -1 --pretty="%ct")}
export CIRQ_TESTING_RANDOM_SEED

pytest ${rest} "${changed[@]}"
5 changes: 2 additions & 3 deletions cirq-core/cirq/contrib/acquaintance/gates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from string import ascii_lowercase as alphabet
from typing import Optional, Sequence, Tuple

import numpy as np
import numpy
import pytest

import cirq
Expand Down Expand Up @@ -232,9 +232,8 @@ def test_swap_network_init_error():
cca.SwapNetworkGate((3,))


rng = np.random.default_rng()
part_lens_and_acquaintance_sizes = [
[[l + 1 for l in rng.poisson(size=n_parts, lam=lam)], rng.poisson(4)]
[[l + 1 for l in numpy.random.poisson(size=n_parts, lam=lam)], numpy.random.poisson(4)]
for n_parts, lam in product(range(2, 20, 3), range(1, 4))
]

Expand Down
8 changes: 4 additions & 4 deletions cirq-core/cirq/ops/common_gates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1042,10 +1042,10 @@ def test_ixyz_circuit_diagram():
@pytest.mark.parametrize(
'theta,exp',
[
{sympy.Symbol("theta"), 1 / 2},
{np.pi / 2, 1 / 2},
{np.pi / 2, sympy.Symbol("exp")},
{sympy.Symbol("theta"), sympy.Symbol("exp")},
(sympy.Symbol("theta"), 1 / 2),
(np.pi / 2, 1 / 2),
(np.pi / 2, sympy.Symbol("exp")),
(sympy.Symbol("theta"), sympy.Symbol("exp")),
],
)
def test_rxyz_exponent(theta, exp):
Expand Down
13 changes: 8 additions & 5 deletions cirq-core/cirq/protocols/json_serialization_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,11 +537,14 @@ def _list_public_classes_for_tested_modules():
# to remove DeprecationWarning noise during test collection
with warnings.catch_warnings():
warnings.simplefilter("ignore")
return [
(mod_spec, o, n)
for mod_spec in MODULE_TEST_SPECS
for (o, n) in mod_spec.find_classes_that_should_serialize()
]
return sorted(
(
(mod_spec, n, o)
for mod_spec in MODULE_TEST_SPECS
for (n, o) in mod_spec.find_classes_that_should_serialize()
),
key=lambda mno: (str(mno[0]), mno[1]),
)


@pytest.mark.parametrize(
Expand Down
17 changes: 17 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import random

# allow CI execution of isolated_packages_test.py without numpy
try:
import numpy
except ImportError:
# coverage: ignore
numpy = None


def pytest_configure(config):
# Ignore deprecation warnings in python code generated from our protobuf definitions.
Expand All @@ -35,3 +45,10 @@ def pytest_addoption(parser):
default=False,
help="run Rigetti integration tests",
)


# skip seeding for unset or empty CIRQ_TESTING_RANDOM_SEED
if numpy is not None and os.environ.get('CIRQ_TESTING_RANDOM_SEED'):
rngseed = int(os.environ['CIRQ_TESTING_RANDOM_SEED'])
random.seed(rngseed)
numpy.random.seed(rngseed)

0 comments on commit 0824992

Please sign in to comment.