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

Add support for Catch2 v3 #102

Closed
bluecube opened this issue Apr 27, 2023 · 12 comments
Closed

Add support for Catch2 v3 #102

bluecube opened this issue Apr 27, 2023 · 12 comments

Comments

@bluecube
Copy link

As far as I can tell, v3 binaries don't work with the current Catch2 support, because --list-test-names-only command line option is missing.

@nrbnlulu
Copy link

Does your tests gets collected?

@bluecube
Copy link
Author

No, it doesn't.

@nrbnlulu
Copy link

nrbnlulu commented Apr 27, 2023

just crafted this minimal thing

import json
import re
import subprocess
from functools import cached_property
from pathlib import Path
from typing import Optional

import pytest
from typing_extensions import TypedDict

build_dir = Path(__file__).parent.parent / "build"


class TestProperty(TypedDict):
    name: str
    value: str


class TestDefinition(TypedDict):
    name: str
    properties: list[TestProperty]


class CtestDiscoveryResult(TypedDict):
    tests: list[TestDefinition]


class CtestTestCommand:
    def __init__(self, test_name: str) -> None:
        self._data: list[str] = ["ctest", "-R"]
        self.test_name: str = test_name
        self.ret_res: Optional[subprocess.CompletedProcess] = None

    def add_command(self, command: str):
        self._data.append(command)

    @cached_property
    def failed_log(self) -> str | None:
        assert self.ret_res
        try:
            match = re.findall("(in: )(.*)(\\.log)", self.ret_res.stderr.decode())
            log_file = match[0][1]
        except IndexError:
            return None
        return Path(log_file + ".log").resolve(True).read_text()

    def run(self) -> None:
        self.ret_res = subprocess.run(
            [*self._data, self.test_name],
            cwd=build_dir.resolve(True),
            capture_output=True,
        )


def collect_tests() -> list[CtestTestCommand]:
    ret: list[CtestTestCommand] = []
    res = subprocess.run(
        ["ctest", "--show-only=json-v1"],
        cwd=build_dir.resolve(True),
        capture_output=True,
    )
    data: CtestDiscoveryResult = json.loads(res.stdout)
    for test in data["tests"]:
        ret.append(CtestTestCommand(test["name"]))
    return ret


test_commands = collect_tests()


@pytest.mark.parametrize("command", test_commands, ids=lambda v: v.test_name)
def test_cpp(command: CtestTestCommand):
    command.run()
    if log_file := command.failed_log:
        pytest.fail(msg=f"\n {'-'*8} Test {command.test_name} Failed {'-'*8} \n {log_file}")

Just point it to the build dir and it would do the rest.

@bluecube
Copy link
Author

Wow you're fast :) . Thank you. I hope I'll be able to try it out later today.

@nicoddemus
Copy link
Member

If it works, happy to review/merge a PR. 👍

@nrbnlulu
Copy link

@nicoddemus I don't use any library code though, I just find tests and run them via parameterize
something close to what I suggested in #20

@nicoddemus
Copy link
Member

No worries, but I like to mention that to encourage someone interested in Catch2 v3 to contribute.

@bluecube
Copy link
Author

bluecube commented May 2, 2023

@nrbnlulu Your code didn't work for me directly, because I don't use ctest in my project, I needed to call the test binary directly. But it gave me some starting point and I ended up modifying it for my use case ( https://github.com/bluecube/tablog/blob/87506b3b69a873914d6ea726facf4c6c4bf752ec/encoder/tests/test_adapter.py ), so thank you for the push in the right-ish direction :)

I'd still like to have more complete support for v3, though, including specific failed assertions and random generator seed, so I'll try to make a PR.

Should I add Catch2v3Facade, or add it to the existing one?

@nicoddemus
Copy link
Member

Should I add Catch2v3Facade, or add it to the existing one?

Whichever is more convenient: if the changes are small and localized, might make sense to add to the existing facade, however if you need to change every single method to do something different, it might make more sense to write a new facade.

@nrbnlulu
Copy link

nrbnlulu commented May 2, 2023

@bluecube AFAIK if you use catch with Cmake it generates ctest binary for you am I wrong?

@bluecube
Copy link
Author

bluecube commented May 2, 2023

That might be true, but I'm using it with SCons.

@jnewb1
Copy link
Collaborator

jnewb1 commented Sep 14, 2023

closed by: #115

@jnewb1 jnewb1 closed this as completed Sep 14, 2023
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

No branches or pull requests

4 participants