On 3/11/22 16:21, Adrian Moreno wrote: > Use pytest to run unit tests as part of the standard testsuite. > > Acked-by: Eelco Chaudron <[email protected]> > Signed-off-by: Adrian Moreno <[email protected]> > --- > .github/workflows/build-and-test.yml | 3 + > Documentation/intro/install/general.rst | 4 ++ > python/automake.mk | 9 ++- > python/ovs/tests/test_kv.py | 76 +++++++++++++++++++++++++ > python/test_requirements.txt | 3 + > tests/atlocal.in | 19 +++++++ > tests/automake.mk | 1 + > tests/pytest.at | 7 +++ > tests/testsuite.at | 1 + > 9 files changed, 121 insertions(+), 2 deletions(-) > create mode 100644 python/ovs/tests/test_kv.py > create mode 100644 python/test_requirements.txt > create mode 100644 tests/pytest.at > > diff --git a/.github/workflows/build-and-test.yml > b/.github/workflows/build-and-test.yml > index eac3504e4..44df1c2d5 100644 > --- a/.github/workflows/build-and-test.yml > +++ b/.github/workflows/build-and-test.yml > @@ -123,6 +123,9 @@ jobs: > with: > python-version: '3.9' > > + - name: install python dependencies > + run: pip install -r python/test_requirements.txt
Can we place this after the 'prepare' stage or inside the prepare.sh script? Just to ensure that we have 'wheel' installed before trying to install anything else. > + > - name: create ci signature file for the dpdk cache key > if: matrix.dpdk != '' || matrix.dpdk_shared != '' > # This will collect most of DPDK related lines, so hash will be > different > diff --git a/Documentation/intro/install/general.rst > b/Documentation/intro/install/general.rst > index c4300cd53..711fb98a4 100644 > --- a/Documentation/intro/install/general.rst > +++ b/Documentation/intro/install/general.rst > @@ -181,6 +181,10 @@ following to obtain better warnings: > come from the "hacking" flake8 plugin. If it's not installed, the warnings > just won't occur until it's run on a system with "hacking" installed. > > +- the python packages listed in "python/test_requirements.txt" (compatible > + with pip). If they are installed, the pytest-based Python unit tests will > + be run. > + > You may find the ovs-dev script found in ``utilities/ovs-dev.py`` useful. > > .. _general-install-reqs: > diff --git a/python/automake.mk b/python/automake.mk > index e5501c58e..43a27d3cb 100644 > --- a/python/automake.mk > +++ b/python/automake.mk > @@ -53,6 +53,9 @@ ovs_pyfiles = \ > python/ovs/vlog.py \ > python/ovs/winutils.py > > +ovs_pytests = \ > + python/ovs/tests/test_kv.py > + > # These python files are used at build time but not runtime, > # so they are not installed. > EXTRA_DIST += \ > @@ -66,12 +69,14 @@ EXTRA_DIST += \ > EXTRA_DIST += \ > python/ovs/compat/sortedcontainers/LICENSE \ > python/README.rst \ > - python/setup.py > + python/setup.py \ > + python/test_requirements.txt > > # C extension support. > EXTRA_DIST += python/ovs/_json.c > > -PYFILES = $(ovs_pyfiles) python/ovs/dirs.py $(ovstest_pyfiles) > +PYFILES = $(ovs_pyfiles) python/ovs/dirs.py $(ovstest_pyfiles) $(ovs_pytests) > + > EXTRA_DIST += $(PYFILES) > PYCOV_CLEAN_FILES += $(PYFILES:.py=.py,cover) > > diff --git a/python/ovs/tests/test_kv.py b/python/ovs/tests/test_kv.py > new file mode 100644 > index 000000000..e81804d49 > --- /dev/null > +++ b/python/ovs/tests/test_kv.py > @@ -0,0 +1,76 @@ > +import pytest > + > +from ovs.flows.kv import KVParser, KeyValue > + > + > [email protected]( > + "input_data,expected", > + [ > + ( > + ( > + "cookie=0x0, duration=147566.365s, table=0, n_packets=39, > n_bytes=2574, idle_age=65534, hard_age=65534", # noqa: E501 > + None, > + ), > + [ > + KeyValue("cookie", 0), > + KeyValue("duration", "147566.365s"), > + KeyValue("table", 0), > + KeyValue("n_packets", 39), > + KeyValue("n_bytes", 2574), > + KeyValue("idle_age", 65534), > + KeyValue("hard_age", 65534), > + ], > + ), > + ( > + ( > + > "load:0x4->NXM_NX_REG13[],load:0x9->NXM_NX_REG11[],load:0x8->NXM_NX_REG12[],load:0x1->OXM_OF_METADATA[],load:0x1->NXM_NX_REG14[],mod_dl_src:0a:58:a9:fe:00:02,resubmit(,8)", > # noqa: E501 > + None, > + ), > + [ > + KeyValue("load", "0x4->NXM_NX_REG13[]"), > + KeyValue("load", "0x9->NXM_NX_REG11[]"), > + KeyValue("load", "0x8->NXM_NX_REG12[]"), > + KeyValue("load", "0x1->OXM_OF_METADATA[]"), > + KeyValue("load", "0x1->NXM_NX_REG14[]"), > + KeyValue("mod_dl_src", "0a:58:a9:fe:00:02"), > + KeyValue("resubmit", ",8"), > + ], > + ), > + ( > + ("l1(l2(l3(l4())))", None), > + [KeyValue("l1", "l2(l3(l4()))")] > + ), > + ( > + ("l1(l2(l3(l4()))),foo:bar", None), > + [KeyValue("l1", "l2(l3(l4()))"), KeyValue("foo", "bar")], > + ), > + ( > + ("enqueue:1:2,output=2", None), > + [KeyValue("enqueue", "1:2"), KeyValue("output", 2)], > + ), > + ( > + ("value_to_reg(100)->someReg[10],foo:bar", None), > + [ > + KeyValue("value_to_reg", "(100)->someReg[10]"), > + KeyValue("foo", "bar"), > + ], > + ), > + ], > +) > +def test_kv_parser(input_data, expected): > + input_string = input_data[0] > + decoders = input_data[1] > + tparser = KVParser(input_string, decoders) > + tparser.parse() > + result = tparser.kv() > + assert len(expected) == len(result) > + for i in range(0, len(result)): > + assert result[i].key == expected[i].key > + assert result[i].value == expected[i].value > + kpos = result[i].meta.kpos > + kstr = result[i].meta.kstring > + vpos = result[i].meta.vpos > + vstr = result[i].meta.vstring > + assert input_string[kpos : kpos + len(kstr)] == kstr > + if vpos != -1: > + assert input_string[vpos : vpos + len(vstr)] == vstr > diff --git a/python/test_requirements.txt b/python/test_requirements.txt > new file mode 100644 > index 000000000..6aaee13e3 > --- /dev/null > +++ b/python/test_requirements.txt > @@ -0,0 +1,3 @@ > +pytest > +netaddr > +pyparsing > diff --git a/tests/atlocal.in b/tests/atlocal.in > index a0ad239ec..2426416a0 100644 > --- a/tests/atlocal.in > +++ b/tests/atlocal.in > @@ -222,3 +222,22 @@ export OVS_CTL_TIMEOUT > # matter break everything. > ASAN_OPTIONS=detect_leaks=0:abort_on_error=true:log_path=asan:$ASAN_OPTIONS > export ASAN_OPTIONS > + > +# Check whether Python test requirements are available. > +REQUIREMENT_PATH=$abs_top_srcdir/python/test_requirements.txt $PYTHON3 -c ' > +import os > +import pathlib > +import pkg_resources The 'import sys' is missing here. Without it, the test fails instead of being skipped: Traceback (most recent call last): File "<string>", line 9, in <module> File "/usr/lib/python3.9/site-packages/pkg_resources/__init__.py", line 886, in require needed = self.resolve(parse_requirements(requirements)) File "/usr/lib/python3.9/site-packages/pkg_resources/__init__.py", line 772, in resolve raise DistributionNotFound(req, requirers) pkg_resources.DistributionNotFound: The 'pytest' distribution was not found and is required by the application During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<string>", line 11, in <module> NameError: name 'sys' is not defined ./tests/testsuite: unexpected error probing Python unit test requirements ## ------------------------------- ## ## openvswitch 2.17.90 test suite. ## ## ------------------------------- ## 2497: Pytest unit tests - Python3 FAILED (pytest.at:6) > + > +with pathlib.Path(os.path.join(os.getenv("REQUIREMENT_PATH"))).open() as > reqs: > + for req in pkg_resources.parse_requirements(reqs): > + try: > + pkg_resources.require(str(req)) > + except pkg_resources.DistributionNotFound: > + sys.exit(2) > +' > +case $? in > + 0) HAVE_PYTEST=yes ;; > + 2) HAVE_PYTEST=no ;; > + *) echo "$0: unexpected error probing Python unit test requirements" >&2 > ;; > +esac > diff --git a/tests/automake.mk b/tests/automake.mk > index 0279585cd..e7ffc2691 100644 > --- a/tests/automake.mk > +++ b/tests/automake.mk > @@ -103,6 +103,7 @@ TESTSUITE_AT = \ > tests/ovsdb-rbac.at \ > tests/ovs-vsctl.at \ > tests/ovs-xapi-sync.at \ > + tests/pytest.at \ > tests/stp.at \ > tests/rstp.at \ > tests/interface-reconfigure.at \ > diff --git a/tests/pytest.at b/tests/pytest.at > new file mode 100644 > index 000000000..44a88ed98 > --- /dev/null > +++ b/tests/pytest.at > @@ -0,0 +1,7 @@ > +AT_BANNER([Python unit tests]) > + > +# Run pytest unit tests. > +AT_SETUP([Pytest unit tests - Python3]) Would be nice to have a 'python' keywork defined, so the test will run with TESTSUITEFLAGS='-k python'. > +AT_SKIP_IF([test "$HAVE_PYTEST" = "no"]) > +AT_CHECK([python -m pytest $top_srcdir/python/ovs],[0], [ignore], [ignore]) There should be '$PYTHON3' instead of just 'python'. > +AT_CLEANUP() > diff --git a/tests/testsuite.at b/tests/testsuite.at > index 58adfa09c..14a28b517 100644 > --- a/tests/testsuite.at > +++ b/tests/testsuite.at > @@ -78,3 +78,4 @@ m4_include([tests/mcast-snooping.at]) > m4_include([tests/packet-type-aware.at]) > m4_include([tests/nsh.at]) > m4_include([tests/drop-stats.at]) > +m4_include([tests/pytest.at]) _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
