Generate temporary file/folder c++ GTEST

Although it does not build the temp files, googletest provides two different test macros, TEST and TEST_F, where the latter is fixtured. See the section titled "Test Fixtures: Using the Same Data Config..." at the Primer for much more info on fixtures.

My solution to this problem is to use Boost.Filesystem with a fixtured test. I want to be able to have a named temp subdirectory that is shared for all of the tests. In this case, I am adapting my case to fit the OP's request for a specified suffix.

Includes:

// Boost.Filesystem VERSION 3 required
#include <string>
#include <boost/filesystem.hpp>

Test class definition:

class ArchiveTest : public ::testing::Test {
protected:
    boost::filesystem::path mTempFileRel;
    boost::filesystem::path mTempFileAbs;
    std::ofstream mExampleStream;

    ArchiveTest() {
         mTempFileRel = boost::filesystem::unique_path("%%%%_%%%%_%%%%_%%%%.your_suffix");
         mTempFileAbs = boost::filesystem::temp_directory_path() / mTempFileRel;
         mExampleStream.open(mTempFileAbs);
    }

    ~ArchiveTest() {
        if(mExampleStream.is_open())
        {
            mExampleStream.close();
        }
    }
    // Note there are SetUp() and TearDown() that are probably better for
    // actually opening/closing in case something throws
};

Note: although you can create the file object in the constructor or SetUp() and close in the destructor or TearDown(), I prefer to do that in the test as I do not use the filename created in all tests that are fixtured. Thus, be extra cautious when you use the stream examples.

Here is my use of a file name:

// Tests that an ArchiveFile can be written
TEST_F(ArchiveTest, TestWritingArchive) {
    try
    {
        TheInfo info_;  // some metadata for the archive
        MyArchive archive_; // Custom class for an archive
        archive_.attachToFile(mTempFile, info_);

        ...
    }
    catch(const std::exception& e_)
    {
        FAIL() << "Caught an exception in " << typeid(*this).name()
               << ": " << e_.what();
    }
}

If you are curious about the '%' characters, from the reference on unique_path:

The unique_path function generates a path name suitable for creating temporary files, including directories. The name is based on a model that uses the percent sign character to specify replacement by a random hexadecimal digit.

Notes:

  1. Thanks to Robbie Morrison for the concise answer on temp files that got me started
  2. I copied/pasted excerpts from a much longer class definition and set of tests, so do let me know if anything is unclear or if there are typographical (copy/paste) errors.

You can use mkstemps on some systems, though it is non-standard. From the man page for mkstemp:

The mkstemps() function is like mkstemp(), except that the string in template contains a suffix of suffixlen characters. Thus, template is of the form prefixXXXXXXsuffix, and the string XXXXXX is modified as for mkstemp().

Therefore, you can use mkstemps somewhat like this:

// The template in use. Replace '.suffix' with your needed suffix.
char temp[] = "XXXXXX.suffix";
// strlen is used for ease of illistration.
int fd = mkstemps(temp, strlen(".suffix"));

// Since the template is modified, you now have the name of the file.
puts(temp);

You will need to keep track of the filename so that you can delete it at the end of the program. If you wanted to be able to put all of these files into, say, /tmp, you should be able to add "/tmp/" as a prefix. There doesn't appear for there to be a way for it to create a temporary directory, though.

Tags:

C++

Googletest