I'm currently learning unit testing with google mock What is the usual use of virtual void SetUp()
and virtual void TearDown()
in the google mock? An example scenario with codes would be good.
It's there to factor code that you want to do at the beginning and end of each test, to avoid repeating it.
For example :
namespace {
class FooTest : public ::testing::Test {
protected:
Foo * pFoo_;
FooTest() {
}
virtual ~FooTest() {
}
virtual void SetUp() {
pFoo_ = new Foo();
}
virtual void TearDown() {
delete pFoo_;
}
};
TEST_F(FooTest, CanDoBar) {
// You can assume that the code in SetUp has been executed
// pFoo_->bar(...)
// The code in TearDown will be run after the end of this test
}
TEST_F(FooTest, CanDoBaz) {
// The code from SetUp will have been executed *again*
// pFoo_->baz(...)
// The code in TearDown will be run *again* after the end of this test
}
} // Namespace
Test code has the tendency to be full of code duplication: It is good practice to write individual test methods for testing different aspects of some piece of code under test. This has the consequence that for some tested function there can be quite a number of different test methods. And, all of these methods have to realize (in principle) the following steps:
- Prepare (set up) the execution of the code under test. The goal of this is to ensure that, when executed, the environment and inputs of the code under test are completely under control of the test.
- Execute (exercise) the code under test.
- Evaluate (validate) the results, that is, checking that the actual results match the expectation.
- If necessary, clean up (tear down), such that the subsequent tests can start from a defined starting point. Often in this step allocated resources are freed, created files are deleted etc.
Since these activities are common to all test methods and since there are several test methods per tested functionality, there is likely some amount of code duplication, in particular across the different set up and tear down phases. To overcome this problem, test frameworks offer the possibility to put common setup and teardown code into special methods, in case of Google Test SetUp and TearDown.
The execution model is then the following: First, a fresh instance of the class with the test methods (aka fixture in gtest) is created, which implies that the constructor is called. Second, the SetUp method (if any) is run on that instance. This gives the SetUp method the opportunity to perform all of the setup activities that are common between the different test methods. Third, the respective test method is called (just one of them !). Here, again, setup/exercise/validate/teardown take place, but regarding the setup only those activities have to be done that are not yet covered by the SetUp method. Similarly, only those teardown activities specific for this test method are done within the test method. Fourth, the TearDown method is called to perform the common cleanup activities, and finally the instance is destroyed (destructor called). Then, these five steps are performed for the next test method and so on.
So much for the general idea of SetUp of TearDown. However, there are some things to keep in mind when implementing tests: Surely, SetUp and TearDown can help to reduce code duplication across tests. However, their use can lead to different kinds of problems:
- The code of test methods can become obscure, because some activities relevant for the understanding of how a test works are located in the SetUp method. Sure, experienced developers will know that, when trying to understand a test method, they should also look into SetUp and TearDown, but test code readability is negatively affected.
- The SetUp methods tend to accumulate functionality across test methods: If you have three test methods, and two of them share some setup code, this can be added to the SetUp method. For a later reader of the test code it becomes more difficult to understand which parts of SetUp actually belong to which test method. This also makes it more difficult to make modifications to SetUp, because it becomes more difficult to predict which test methods will be affected by a change.
Therefore, it can be beneficial to go for a different approach to reduce code duplication across test methods. Instead of putting common code into SetUp and TearDown which are called implicitly by the test framework you can do the following: You create helper methods of your own that have easy-to-understand names, like "ensureTrafficLightIsGreen", which contain the respective common setup and teardown code. These methods will, certainly, not be called implicitly before each test method, but instead you would call them explicitly. This leaves a bit of code duplication, but brings the benefit that it becomes clear from the test method itself which setup activities actually take place. Your own helper methods can certainly take parameters, for example "ensureTrafficLightIs(Green)".
© 2022 - 2024 — McMap. All rights reserved.