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

Catch2: support v3 #115

Merged
merged 7 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 39 additions & 9 deletions src/pytest_cpp/catch2.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
import subprocess
import tempfile
from typing import Optional
from typing import Sequence
from xml.etree import ElementTree

Expand All @@ -20,11 +21,11 @@ class Catch2Facade(AbstractFacade):
"""

@classmethod
def is_test_suite(
def get_catch_version(
cls,
executable: str,
harness_collect: Sequence[str] = (),
) -> bool:
) -> Optional[str]:
Copy link
Member

Choose a reason for hiding this comment

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

If we want to type this correctly, we can either use an enum, or Literal:

Suggested change
) -> Optional[str]:
) -> Optional[Literal["v2", "v3"]]:

args = make_cmdline(harness_collect, executable, ["--help"])
try:
output = subprocess.check_output(
Expand All @@ -33,25 +34,44 @@ def is_test_suite(
universal_newlines=True,
)
except (subprocess.CalledProcessError, OSError):
return False
return None
else:
return "--list-test-names-only" in output
return (
"v2"
if "--list-test-names-only" in output
else "v3"
if "--list-tests" in output
else None
)

@classmethod
def is_test_suite(
cls,
executable: str,
harness_collect: Sequence[str] = (),
) -> bool:
return cls.get_catch_version(executable, harness_collect) in ["v2", "v3"]

def list_tests(
self,
executable: str,
harness_collect: Sequence[str] = (),
) -> list[str]:
"""
Executes test with "--list-test-names-only" and gets list of tests
Executes test with "--list-test-names-only" (v2) or "--list-tests --verbosity quiet" (v3) and gets list of tests
parsing output like this:

1: All test cases reside in other .cpp files (empty)
2: Factorial of 0 is 1 (fail)
2: Factorials of 1 and higher are computed (pass)
"""
# This will return an exit code with the number of tests available
args = make_cmdline(harness_collect, executable, ["--list-test-names-only"])
exec_args = (
["--list-test-names-only"]
if self.get_catch_version(executable, harness_collect) == "v2"
else ["--list-tests", "--verbosity quiet"]
)
args = make_cmdline(harness_collect, executable, exec_args)
try:
output = subprocess.check_output(
args,
Expand All @@ -77,6 +97,11 @@ def run_test(
On Windows, ValueError is raised when path and start are on different drives.
In this case failing back to the absolute path.
"""
catch_version = self.get_catch_version(executable, harness)

if catch_version is None:
raise Exception("Invalid Catch Version")

try:
xml_filename = os.path.join(os.path.relpath(temp_dir), "cpp-report.xml")
except ValueError:
Expand All @@ -97,7 +122,7 @@ def run_test(
except subprocess.CalledProcessError as e:
output = e.output

results = self._parse_xml(xml_filename)
results = self._parse_xml(xml_filename, catch_version)

for executed_test_id, failures, skipped in results:
if executed_test_id == test_id:
Expand All @@ -123,11 +148,16 @@ def run_test(
return [failure], output

def _parse_xml(
self, xml_filename: str
self, xml_filename: str, catch_version: str
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
self, xml_filename: str, catch_version: str
self, xml_filename: str, catch_version: Literal["v2", "v3"]

) -> Sequence[tuple[str, Sequence[tuple[str, int, str]], bool]]:
root = ElementTree.parse(xml_filename)
result = []
for test_suite in root.findall("Group"):
test_suites = (
root.findall("Group")
if catch_version == "v2"
else root.iter("Catch2TestRun")
)
for test_suite in test_suites:
for test_case in test_suite.findall("TestCase"):
test_name = test_case.attrib["name"]
test_result = test_case.find("OverallResult")
Expand Down
5 changes: 4 additions & 1 deletion tests/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
!.gitignore
!*.h
!*.cpp
!*.hpp
!*.cc
!*.py
!*.xml
!README*
!SCons*
!catch.hpp

!catch2_v2
!catch2_v3
16 changes: 12 additions & 4 deletions tests/SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ if 'CXX' in os.environ:

env = Environment(**kwargs)
genv = env.Clone(LIBS=['gtest'] + LIBS)
c2env = env.Clone(CPPPATH=['.'])
c2env = env.Clone(CPPPATH=['.', 'catch2_v2'])

Export('env genv c2env')
catch2_v3 = env.Library('catch2_v3', ['catch2_v3/catch.cpp'])

c3env = env.Clone(CPPPATH=['.', 'catch2_v3'], LIBS=[catch2_v3])

Export('env genv c2env c3env')

genv.Program('gtest.cpp')
genv.Program('gtest_args.cpp')
Expand All @@ -39,8 +43,12 @@ boost_files = [
for filename in boost_files:
env.Program(filename)

c2env.Program('catch2_success.cpp')
c2env.Program('catch2_failure.cpp')
for env, label in [(c3env, "_v3"), (c2env, "")]:
catch2_success = env.Object(f'catch2_success{label}', 'catch2_success.cpp')
catch2_failure = env.Object(f'catch2_failure{label}', 'catch2_failure.cpp')

env.Program(catch2_success)
env.Program(catch2_failure)

SConscript('acceptance/googletest-samples/SConscript')
SConscript('acceptance/boosttest-samples/SConscript')
Expand Down
File renamed without changes.
Loading
Loading