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

Run a piece of setup once only #1602

Closed
bna080 opened this issue Apr 17, 2019 · 7 comments
Closed

Run a piece of setup once only #1602

bna080 opened this issue Apr 17, 2019 · 7 comments
Labels
Query Resolved - pending review Issue waiting for feedback from the original author

Comments

@bna080
Copy link

bna080 commented Apr 17, 2019

We are writing unit tests where for some test cases we need to run a specific part of the setup and tear-down (say one line of code) once before first section is run and once after all the sections in the test case are done. We would like to do it this way because this specific part of setup and tear-down takes a long time to execute which slows down the total test time.
Is there a way how to achieve this with Catch? I know it sort of breaks the Catch logic, but I have not found a clean way how to do it looking at the Catch Reference and running the "slow" command before and after every section execution just takes too much time.

@horenmar
Copy link
Member

You should be able to use Event Listeners, specifically the testCaseStarting and testCaseEnded hooks.

This has the disadvantage of putting the init and uninit code outside of the main test case, but the advantage of letting you do exactly what you want.

@horenmar horenmar added the Query label Apr 17, 2019
@bna080
Copy link
Author

bna080 commented Apr 19, 2019

Thank you, this almost works for me. However, in the testCaseStarting/testCaseEnded handlers I need to perform operations on an object which is created in the test case itself and which is also accessed and used in the sections of the test case. Is there a way to access such an object, or pass a reference to it to the handlers?

@horenmar
Copy link
Member

There is not, the events are called before the test case is first run (and thus before such object exists) and after the test case is last run (and thus the object is dead at that point). This means that you will also need to introduce some global state.

Alternatively, if the destruction part is not overly important (e.g. you are fine with the destruction happening after the end of all the tests) and the init is basically a constructor, you could abuse a static variable, which will be initialized exactly once and will be destructed at the end of the program.

@bna080
Copy link
Author

bna080 commented Apr 25, 2019

Ah, of course you are right, my object does not exist at that point.
I have been using a static variable until now and it works fine, but I need to do multiple operations on it once before all the tests and once after all the tests. That I have now in a special section which always has to be the first one and another one which is the last one. Not ideal, but it works. Anyway, I will look into using the listeners with a global station as you suggested.

@horenmar horenmar added the Resolved - pending review Issue waiting for feedback from the original author label Apr 28, 2019
@bna080 bna080 closed this as completed May 3, 2019
@bna080 bna080 reopened this May 3, 2019
@ficzerepeti
Copy link

I'd like to add that I'm also interested in solving the described issue in a nicer way than using static variables or writing custom code listening to events.

I thought a SetupBeforeFirstRun and TearDownAfterLastRun macros could be introduced (maybe with better names).

TEST_CASE("This is a test", "[NiceTag]")
{
    static std::optional<MyVeryTimeConsumingObject> objectToSetup;

    SetupBeforeFirstRun
    {
        ... // do some stuff
        objectToSetup.emplace(param1, param2);
        ... // do more stuff
    }

    .... // test things
    const auto queryResult = objectToSetup->Query(queryTxt); // use object
    .... // do more testing

    TearDownAfterLastRun
    {
        objectToSetup.reset();
    }
}

Is this something that would be welcome in Catch2 by @horenmar or other maintainers?

@ptc-dshakir
Copy link

@ficzerepeti This is an interesting idea that could potentially be useful in our case as well. One can work around the setup step by using a static variable, but the tear-down step is trickier.

@horenmar I'm not entirely sure when the testCaseEnded hook fires for instance in a TEST_CASE with a number of GENERATEd iterations - does it fire when each iteration is about to end, or on the last one?

@horenmar
Copy link
Member

horenmar commented Sep 7, 2021

@ptc-dshakir testCaseStarting fires before the test case is entered for the first time, and testCaseEnded fires after the test case has been exited for the last time.

horenmar added a commit that referenced this issue Aug 5, 2024
…tent fixtures throughout a TEST_CASE (#2885)

This PR introduces a new `TEST_CASE` macro called `TEST_CASE_PERSISTENT_FIXTURE`. `TEST_CASE_PERSISTENT_FIXTURE` offers the same functionality as `TEST_CASE_METHOD` except for one difference. The object on which the test method is invoked is only created once for all invocations of the test case. The object is created just after the `testCaseStarting` event is broadcast and the object is destroyed just before the `testCaseEnding` event is broadcast.

The main motivation for this new functionality is to allow `TEST_CASE`s to do expensive setup and teardown once per `TEST_CASE`, without having to resort to abusing event listeners or static function variables with manual initialization.


Implements #1602

---------

Co-authored-by: Martin Hořeňovský <[email protected]>
@horenmar horenmar closed this as completed Aug 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Query Resolved - pending review Issue waiting for feedback from the original author
Projects
None yet
Development

No branches or pull requests

4 participants