Skip to content

Commit b20c4b8

Browse files
committed
TST: use pytest, instead of nose
for compatibility with Python 3.10. - REL: add `pytest >= 4.6.11` to the argument `tests_require` of the function `setuptools.setup` in the script `setup.py`. This lower bound has been selected to ensure compatibility with both Python 3 and Python 2.7. See below for details. - REL: add `pytest >= 4.6.11` to file `requirements.txt` - REL: remove `nose` from argument `tests_require` of the function `setuptools.setup` in script `setup.py` - REL: remove `nose` from file `requirements.txt` - CI: update file `.travis.yml` - CI: remove the collection of coverage measurements on Travis CI, because these measurements do not collect Cython coverage with the build configuration currently used for CI testing. - DEV: remove `coveralls` from the file `requirements.txt`, because the package `coveralls` was used only on Travis CI. - TST: add a configuration file `tests/pytest.ini` and include it in `MANIFEST.in` - GIT: ignore `.pytest_cache/` in `.gitignore` ## Motivation The change from [`nose == 1.3.7`]( https://pypi.org/project/nose/1.3.7/#history) to [`pytest`]( https://pypi.org/project/pytest) is motivated by compatibility with Python 3.10. ## `nose` is incompatible with Python 3.10 The package `nose`, which was used to run the tests of `dd`, is not compatible with Python 3.10 (for details, read the last section below). Also, `nose` uses the `imp` module from CPython's standard library. The module `imp` [is deprecated]( https://docs.python.org/3.10/library/imp.html), so it may be removed in some future Python version. ## Summary of transition to `pytest` In summary, using `pytest` with the existing tests requires adding a [configuration file `tests/pytest.ini`]( https://docs.pytest.org/en/latest/reference/customize.html#configuration-file-formats) to tell `pytest` which functions, classes, and methods to collect tests from (called "discovery" of tests). The [parameter `--continue-on-collection-errors`]( https://docs.pytest.org/en/latest/reference/reference.html#command-line-flags) tells `pytest` to not stop in case any test module fails to import, and to continue with running the tests. The ability to run the tests when some `dd` C extension modules are not installed is necessary. After transitioning the tests to `pytest`, the tests have been confirmed to run successfully: - on Python 2.7 with `pytest == 4.6.11`, and - on Python 3.9 with `pytest == 6.2.4`. ## Considering using `unittest` For writing `dd` tests, the module [`unittest`]( https://docs.python.org/3/library/unittest.html) (part of CPython's standard library) suffices. For *discovering* the tests, `unittest` seems to require that tests be methods of subclasses of the class `unittest.TestCase`. This is not the case in the tests of `dd` tests. Using `pytest` allows changing the test runner from `nosetests` with minimal changes to the tests themselves. Test discovery using `unittest` could possibly be implemented by adding a file `tests/__init__.py`, and defining in that file a function `load_tests`, following the [documentation of `unittest`]( https://docs.python.org/3/library/unittest.html#unittest.TestLoader.discover). In any case, it is simpler to use `pytest`, which requires only a configuration file. If `unittest` encounters an `ImportError` during collection of the tests (i.e., when `unittest` tries to import test modules), then it stops. There does not appear to be any way to tell `unittest` to continue and run the rest of the test modules (those that *could* be imported). ## Usage of `nose` The dependence on `nose` was minimal. Only one function was used from `nose`: the function `nose.tools.assert_raises`. The function `assert_raises` is dynamically defined [in the module `nose.tools.trivial`]( https://github.com/nose-devs/nose/blob/release_1.3.7/nose/tools/trivial.py#L32-L54) by instantiating the class `unittest.TestCase`, and setting `assert_raises` to equal the [bound method `assertRaises`]( https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises) of the instance of `TestCase`. So the function `assert_raises` from `nose` is a PEP8-compliant binding for the method `unittest.TestCase.assertRaises`. Reading the code of `unittest`: - <https://github.com/python/cpython/blob/6fdc4d37f3fdbc1bd51f841be6e5e4708a3b8798/Lib/unittest/case.py#L156-L243> - <https://github.com/python/cpython/blob/6fdc4d37f3fdbc1bd51f841be6e5e4708a3b8798/Lib/unittest/case.py#L704-L735> it follows that the usage: ```python with nose.tools.assert_raises(AssertionError): foo(1, 2) ``` is equivalent to the following code (`AssertionError` here is used as an example): ```python with unittest.TestCase().assertRaises(AssertionError): foo(1, 2) ``` ## Replacing usage of `nose` with `pytest` in test code The [context manager `pytest.raises`]( https://docs.pytest.org/en/latest/reference/reference.html#pytest-raises) is a [drop-in replacement]( https://en.wikipedia.org/wiki/Drop-in_replacement) for the function `nose.tools.assert_raises`: ```python with pytest.raises(AssertionError): foo(1, 2) ``` Also, the tests can still be run with `nosetests` on Python versions where `nose` is still available. ## Replacing the test runner `nosetests` with `pytest` - `pytest` correctly recognized the test files by default - `pytest` does not recognize by default methods of classes that do not start with "Test" as test methods. The configuration file is necessary for changing this behavior of `pytest` (in particular, the command-line parameter `-k` did not seem to work for classes). Relevant documentation: - <https://docs.pytest.org/en/latest/explanation/goodpractices.html#conventions-for-python-test-discovery> - <https://docs.pytest.org/en/latest/example/pythoncollection.html#changing-naming-conventions> - <https://docs.pytest.org/en/latest/how-to/nose.html> - <https://docs.pytest.org/en/latest/reference/reference.html#confval-python_classes> - <https://docs.pytest.org/en/latest/reference/reference.html#confval-python_functions> - <https://docs.pytest.org/en/latest/reference/reference.html#confval-python_files> - The call `pytest tests/foo_test.py` imports the package `dd` from `site-packages` (assuming that the module `foo_test.py` contains the statement `import dd`). So the default behavior of `pytest` is as intended. In contrast, `nosetests tests/foo_test.py` imports the package `dd` from the local directory `dd/`, even though `dd` *is* installed under `site-packages`. In any case, `pytest` is called from within the directory `tests/`, as was done for `nosetests`. Both: - `python -m pytest tests/foo_test.py` and - `PYTHONPATH=. pytest tests/foo_test.py` result in importing `dd` from the local directory `dd/`. Relevant documentation: - <https://docs.pytest.org/en/latest/explanation/pythonpath.html#invoking-pytest-versus-python-m-pytest> - <https://docs.pytest.org/en/latest/how-to/usage.html#invoke-python> As remarked above, the parameter [`--continue-on-collection-errors`]( https://docs.pytest.org/en/latest/reference/reference.html#command-line-flags) of `pytest` needs to be used for running the tests when some of the C extension modules are not installed. For example: ``` cd tests/ pytest -v --continue-on-collection-errors . ``` To activate [Python's development mode]( https://docs.python.org/3/library/devmode.html): ``` cd tests/ python -X dev -m pytest -vvv --continue-on-collection-errors . ``` ## Further remarks Observations about `pytest`: - detects assertions that failed, and marks their source lines - avoids the deprecated `imp` module (of the standard library) that `nose` uses (and thus the associated `DeprecationWarning`) <https://docs.python.org/3.10/library/imp.html> - running the tests of `dd` with `pytest` revealed several `DeprecationWarning`s that were previously not shown by `nose` (these warnings were about invalid escape sequences due to backslashes appearing in non-raw strings). [`pytest == 6.2.4`](https://pypi.org/project/pytest/6.2.4) is not compatible with Python 2.7. [`pytest == 4.6.11`](https://pypi.org/project/pytest/4.6.11/) is the latest version of `pytest` that is compatible with Python 2.7 (released on June 5, 2020). `pytest` specifies `python_requires` [PEP 345]( https://www.python.org/dev/peps/pep-0345/#requires-python), [PEP 503]( https://www.python.org/dev/peps/pep-0503/): - <https://github.com/pytest-dev/pytest/blob/4.6.11/setup.cfg#L48> - <https://github.com/pytest-dev/pytest/blob/5.0.0/setup.cfg#L43> So including `pytest>=4.6.11` in the file `requirements.txt` suffices to install, on each Python version, the latest version of `pytest` that is compatible with that Python version. This simplifies testing on CI, and packaging. In other words, conditional installations in the file `.travis.yml` are not needed for `pytest`, neither conditional definition of `tests_require` in the script `setup.py`. This approach leaves implicit the upper bound on `pytest` in `tests_require`. This upper bound is specified explicitly by `pytest` itself, depending on the Python version of the interpreter. It appears that `pip == 9.0.0` and `setuptools == 24.2.0` are required, to correctly implement `python_requires`: - <https://pip.pypa.io/en/stable/news/#v9-0-0> - <https://setuptools.readthedocs.io/en/latest/history.html#v24-2-1> ## How replacing usage of `nose` with `unittest` would have looked like A way to replace `nose` could have been to add a module `tests/utils.py` containing: ```python """Common functionality for tests.""" import unittest _test_case = unittest.TestCase() assert_raises = _test_case.assertRaises ``` which is close to what `nose` does. The function `assert_raises` could then be imported from the module `utils` in test modules, and used. Using `pytest` avoids the need for this workaround. ## Details about the incompatibility of `nose` with Python 3.10 [`nose == 1.3.7`]( https://pypi.org/project/nose/1.3.7/#history) imports in Python 3.10. Running `nosetests` fails, due to imports from the module `collections` of classes that have moved to the module `collections.abc`. Relevant information about CPython changes in `collections` (removal of ABCs): - <python/cpython#23754> - <https://bugs.python.org/issue37324> - <https://docs.python.org/3.10/library/collections.abc.html#collections-abstract-base-classes> - Deprecation since Python 3.3, present until Python 3.9: <https://docs.python.org/3.9/library/collections.html#module-collections> - Removed in Python 3.10: <https://docs.python.org/3.10/whatsnew/3.10.html#removed> ## About skipping tests The decorator `unittest.skipIf` is recognized by `pytest`, and skipped tests are correctly recorded and reported. In any case, note also the `pytest` test-skipping facilities: - <https://docs.pytest.org/en/latest/how-to/skipping.html> - <https://docs.pytest.org/en/latest/how-to/unittest.html> - <https://docs.pytest.org/en/latest/example/simple.html#control-skipping-of-tests-according-to-command-line-option> ## About passing `-X dev` to `python` in the `Makefile` The argument `dev` is available for the `python` option [`-X` only on Python 3.7 and higher]( https://docs.python.org/3/library/devmode.html#devmode). So the `Makefile` rules where `-X dev` appears are not compatible with ealier Python versions supported by `dd`. This is not an issue: the development environment is intended to be Python 3.9 or higher, so there is no issue with using `-X dev`. ## Avoiding interaction between tests via class attributes Avoid class attributes in test classes. Use [data attributes][1] instead. Initialize the data attributes in setup methods of the test classes, as is common practice. This approach avoids interaction (via class attributes) between test scripts that import the same modules of common tests. With `nose`, this kind of interaction apparently did not occur, as observed by test failures that were expected to happen. However, `pytest` apparently runs tests in a way that changes to imported modules (e.g., class attributes) persist between different test scripts. This `pytest` behavior was observed by the disappearance of test failures when running with `pytest` (the test failures were observable with `pytest` only when telling `pytest` to run individual test scripts, instead of collecting tests from all test scripts. The cause of the issue with `pytest` was the modification of class attributes (not [data attributes][1]) from the importing module, of classes in the imported module. The modifications were done by setting the class attribute `DD` that defines the BDD or ZDD manager class. Both the scripts `cudd_test.py` and `autoref_test.py` made modifications. The end result was `autoref` tests being run using the class `dd.cudd.BDD`. Using data attributes, instead of class attributes, and subclassing, avoids this kind of erroneous testing. This approach is explicit [PEP 20][4]. [1]: https://docs.python.org/3/tutorial/classes.html#instance-objects [2]: https://github.com/pytest-dev/pytest-xdist [3]: https://github.com/pytest-dev/pytest-forked [4]: https://www.python.org/dev/peps/pep-0020/
1 parent ec51447 commit b20c4b8

17 files changed

+124
-93
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.coverage
22
.cache
3+
.pytest_cache/
34
todo.txt
45
dd/_version.py
56
cython_debug/*

.travis.yml

+1-4
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,4 @@ install:
4343

4444
script:
4545
- cd tests/
46-
- nosetests --with-coverage --cover-package=dd
47-
48-
after_success:
49-
- coveralls
46+
- pytest -v --continue-on-collection-errors .

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
## 0.5.7
55

6+
- require `pytest >= 4.6.11`, instead of `nose`, for Python 3.10 compatibility
7+
68
API:
79

810
- return memory size in bytes from methods `dd.cudd.BDD.statistics` and

MANIFEST.in

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ include AUTHORS
66
include requirements.txt
77
include download.py
88
include tests/README.md
9+
include tests/pytest.ini
910
include tests/inspect_cython_signatures.py
1011
include tests/common.py
1112
include tests/common_bdd.py

Makefile

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
# The script `rtests.py` below is an adaptation of:
2-
# https://github.com/tulip-control/tulip-control/blob/master/run_tests.py
3-
41
wheel_file := $(wildcard dist/*.whl)
52

63
.PHONY: cudd install test
@@ -12,15 +9,16 @@ build_cudd: clean cudd install test
129
build_sylvan: clean
1310
-pip uninstall -y dd
1411
python setup.py install --sylvan
15-
rtests.py --rednose
12+
pip install pytest
13+
make test
1614

1715
sdist_test: clean
1816
python setup.py sdist --cudd --buddy
1917
cd dist; \
2018
pip install dd*.tar.gz; \
2119
tar -zxf dd*.tar.gz
22-
pip install nose rednose
23-
rtests.py --rednose
20+
pip install pytest
21+
make -C dist/dd*/ -f ../../Makefile test
2422

2523
sdist_test_cudd: clean
2624
pip install cython ply
@@ -30,8 +28,8 @@ sdist_test_cudd: clean
3028
tar -zxf dd*.tar.gz; \
3129
cd dd*; \
3230
python setup.py install --fetch --cudd
33-
pip install nose rednose
34-
rtests.py --rednose
31+
pip install pytest
32+
make -C dist/dd*/ -f ../../Makefile test
3533

3634
# use to create source distributions for PyPI
3735
sdist: clean
@@ -69,7 +67,14 @@ develop:
6967

7068
test:
7169
cd tests/; \
72-
nosetests -v
70+
python -X dev -m pytest -v --continue-on-collection-errors .
71+
# `pytest -Werror` turns all warnings into errors
72+
# https://docs.pytest.org/en/latest/how-to/capture-warnings.html
73+
# including pytest warnings about unraisable exceptions:
74+
# https://docs.pytest.org/en/latest/how-to/failures.html
75+
# #warning-about-unraisable-exceptions-and-unhandled-thread-exceptions
76+
# https://docs.pytest.org/en/latest/reference/reference.html
77+
# #pytest.PytestUnraisableExceptionWarning
7378

7479
test_abc:
7580
python -X dev tests/inspect_cython_signatures.py

README.md

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
[![Build Status][build_img]][travis]
2-
[![Coverage Status][coverage]][coveralls]
32

43

54
About
@@ -324,14 +323,15 @@ The modules `dd.cudd` and `dd.cudd_zdd` in the wheel dynamically link to the:
324323
Tests
325324
=====
326325

327-
Require [`nose`](https://pypi.python.org/pypi/nose). Run with:
326+
Use [`pytest`](https://pypi.org/project/pytest). Run with:
328327

329328
```shell
330329
cd tests/
331-
nosetests
330+
pytest -v --continue-on-collection-errors .
332331
```
333332

334333
Tests of Cython modules that were not installed will fail.
334+
The code is covered well by tests.
335335

336336

337337
License
@@ -341,5 +341,3 @@ License
341341

342342
[build_img]: https://travis-ci.com/tulip-control/dd.svg?branch=master
343343
[travis]: https://travis-ci.com/tulip-control/dd
344-
[coverage]: https://coveralls.io/repos/tulip-control/dd/badge.svg?branch=master
345-
[coveralls]: https://coveralls.io/r/tulip-control/dd?branch=master

requirements.txt

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ cython==0.29.24
33

44

55
# dev
6-
nose==1.3.7
6+
pytest>=4.6.11
77
gitpython
88
grip
9-
coveralls

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
'pydot >= 1.2.2',
5353
'setuptools >= 19.6']
5454
TESTS_REQUIRE = [
55-
'nose >= 1.3.4']
55+
'pytest >= 4.6.11']
5656
CLASSIFIERS = [
5757
'Development Status :: 2 - Pre-Alpha',
5858
'Intended Audience :: Developers',

tests/autoref_test.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,22 @@
33

44
from dd import autoref as _bdd
55
import dd.bdd
6-
from nose.tools import assert_raises
76

8-
from common import Tests
9-
from common_bdd import Tests as BDDTests
7+
import common
8+
import common_bdd
109

1110

1211
logging.getLogger('astutils').setLevel('ERROR')
1312

1413

15-
Tests.DD = _bdd.BDD
16-
BDDTests.DD = _bdd.BDD
14+
class Tests(common.Tests):
15+
def setup_method(self):
16+
self.DD = _bdd.BDD
17+
18+
19+
class BDDTests(common_bdd.Tests):
20+
def setup_method(self):
21+
self.DD = _bdd.BDD
1722

1823

1924
def test_str():

tests/bdd_test.py

+24-24
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from dd import bdd as _bdd
99
import networkx as nx
1010
import networkx.algorithms.isomorphism as iso
11-
from nose.tools import assert_raises
11+
import pytest
1212

1313

1414
class BDD(_BDD):
@@ -60,9 +60,9 @@ def test_add_var():
6060
assert b.vars['y'] == 5, b.vars
6161
assert j == 5, j
6262
# attempt to add var at an existing level
63-
with assert_raises(AssertionError):
63+
with pytest.raises(AssertionError):
6464
b.add_var('z', level=35)
65-
with assert_raises(AssertionError):
65+
with pytest.raises(AssertionError):
6666
b.add_var('z', level=5)
6767
#
6868
# mixing automated and
@@ -75,14 +75,14 @@ def test_add_var():
7575
assert 'y' in b.vars, b.vars
7676
assert b.vars['x'] == 2, b.vars
7777
assert b.vars['y'] == 1, b.vars
78-
with assert_raises(AssertionError):
78+
with pytest.raises(AssertionError):
7979
b.add_var('z')
8080
b.add_var('z', level=0)
8181

8282

8383
def test_var():
8484
b = BDD()
85-
with assert_raises(AssertionError):
85+
with pytest.raises(AssertionError):
8686
b.var('x')
8787
j = b.add_var('x')
8888
u = b.var('x')
@@ -99,17 +99,17 @@ def test_assert_consistent():
9999
g = x_or_y()
100100
assert g.assert_consistent()
101101
g._succ[2] = (5, 1, 2)
102-
with assert_raises(AssertionError):
102+
with pytest.raises(AssertionError):
103103
g.assert_consistent()
104104
g = x_or_y()
105105
g.roots.add(2)
106106
g._succ[4] = (0, 10, 1)
107-
with assert_raises(AssertionError):
107+
with pytest.raises(AssertionError):
108108
g.assert_consistent()
109109
g = x_or_y()
110110
g.roots.add(2)
111111
g._succ[1] = (2, None, 1)
112-
with assert_raises(AssertionError):
112+
with pytest.raises(AssertionError):
113113
g.assert_consistent()
114114
g = x_and_y()
115115
assert g.assert_consistent()
@@ -120,7 +120,7 @@ def test_level_to_variable():
120120
g = BDD(ordering)
121121
assert g.var_at_level(0) == 'x'
122122
assert g.var_at_level(1) == 'y'
123-
with assert_raises(AssertionError):
123+
with pytest.raises(AssertionError):
124124
g.var_at_level(10)
125125

126126

@@ -209,7 +209,7 @@ def test_count():
209209
assert r == 6, r
210210
r = g.count(-4, 3)
211211
assert r == 2, r
212-
with assert_raises(Exception):
212+
with pytest.raises(Exception):
213213
g.count()
214214
r = g.count(4)
215215
assert r == 3, r
@@ -472,10 +472,10 @@ def test_find_or_add():
472472
assert refv == refv_, (refv, refv_)
473473
assert refw == refw_, (refw, refw_)
474474
# only non-terminals can be added
475-
with assert_raises(AssertionError):
475+
with pytest.raises(AssertionError):
476476
g.find_or_add(2, -1, 1)
477477
# low and high must already exist
478-
with assert_raises(AssertionError):
478+
with pytest.raises(AssertionError):
479479
g.find_or_add(0, 3, 4)
480480
# canonicity of complemented edges
481481
# v < 0, w > 0
@@ -527,7 +527,7 @@ def test_next_free_int():
527527
# full
528528
g._succ = {1, 2, 3}
529529
g.max_nodes = 3
530-
with assert_raises(Exception):
530+
with pytest.raises(Exception):
531531
g._next_free_int(start=1)
532532

533533

@@ -663,7 +663,7 @@ def test_cofactor():
663663
ordering = {'x': 0, 'y': 1, 'z': 2}
664664
g = BDD(ordering)
665665
# u not in g
666-
with assert_raises(AssertionError):
666+
with pytest.raises(AssertionError):
667667
g.let({'x': False, 'y': True, 'z': False}, 5)
668668
# x /\ y
669669
e = g.add_expr(r'x /\ y')
@@ -799,7 +799,7 @@ def test_request_reordering():
799799
ctx._last_len = 1
800800
ctx.length = 3 # >= 2 = 2 * _last_len
801801
# large growth
802-
with assert_raises(_bdd._NeedsReordering):
802+
with pytest.raises(_bdd._NeedsReordering):
803803
_bdd._request_reordering(ctx)
804804
ctx._last_len = 2
805805
ctx.length = 3 # < 4 = 2 * _last_len
@@ -817,20 +817,20 @@ def test_reordering_context():
817817
ctx.assert_(False)
818818
# nested context
819819
ctx._reordering_context = True
820-
with assert_raises(_bdd._NeedsReordering):
820+
with pytest.raises(_bdd._NeedsReordering):
821821
with _bdd._ReorderingContext(ctx):
822822
ctx.assert_(True)
823823
raise _bdd._NeedsReordering()
824824
ctx.assert_(True)
825825
# other exception
826826
ctx._reordering_context = False
827-
with assert_raises(AssertionError):
827+
with pytest.raises(AssertionError):
828828
with _bdd._ReorderingContext(ctx):
829829
ctx.assert_(True)
830830
raise AssertionError()
831831
ctx.assert_(False)
832832
ctx._reordering_context = True
833-
with assert_raises(Exception):
833+
with pytest.raises(Exception):
834834
with _bdd._ReorderingContext(ctx):
835835
raise Exception()
836836
ctx.assert_(True)
@@ -944,7 +944,7 @@ def test_undeclare_vars():
944944
bdd = BDD()
945945
bdd.declare('x', 'y', 'z', 'w')
946946
u = bdd.add_expr(r'y /\ w')
947-
with assert_raises(AssertionError):
947+
with pytest.raises(AssertionError):
948948
bdd.undeclare_vars('z', 'y')
949949

950950

@@ -1100,7 +1100,7 @@ def test_rename():
11001100
assert r == r_, (r, r_)
11011101
# u not in bdd
11021102
dvars = {'x': 'xp'}
1103-
with assert_raises(AssertionError):
1103+
with pytest.raises(AssertionError):
11041104
g.let(dvars, 1000)
11051105
# y essential for u
11061106
dvars = {'x': 'y'}
@@ -1153,16 +1153,16 @@ def test_image_rename_map_checks():
11531153
assert r == 1, r
11541154
# overlapping keys and values
11551155
rename = {0: 1, 1: 2}
1156-
with assert_raises(AssertionError):
1156+
with pytest.raises(AssertionError):
11571157
_bdd.image(1, 1, rename, qvars, bdd)
1158-
with assert_raises(AssertionError):
1158+
with pytest.raises(AssertionError):
11591159
_bdd.preimage(1, 1, rename, qvars, bdd)
11601160
# may be in support after quantification ?
11611161
trans = bdd.add_expr('x => xp')
11621162
source = bdd.add_expr(r'x /\ y')
11631163
qvars = {0}
11641164
rename = {1: 0, 3: 2}
1165-
with assert_raises(AssertionError):
1165+
with pytest.raises(AssertionError):
11661166
_bdd.image(trans, source, rename, qvars, bdd)
11671167
# in support of `target` ?
11681168
qvars = set()
@@ -1237,7 +1237,7 @@ def test_assert_valid_ordering():
12371237
ordering = {'x': 0, 'y': 1}
12381238
_bdd._assert_valid_ordering(ordering)
12391239
incorrect_ordering = {'x': 0, 'y': 2}
1240-
with assert_raises(AssertionError):
1240+
with pytest.raises(AssertionError):
12411241
_bdd._assert_valid_ordering(incorrect_ordering)
12421242

12431243

0 commit comments

Comments
 (0)