Can't get test to run on Visual Studio 2019 using Microsoft CppUnitTest Framework

472 Views Asked by At

I've a function std::vector<Token> tokenize(const std::string& s) that I want to unit test. The Token struct is defined as follows:

enum class Token_type { plus, minus, mult, div, number };

struct Token {
    Token_type type;
    double value;
}

I have set up CppUnitTest and can get toy tests such as 1 + 1 == 2 to run. But when I try to run a test on my tokenize function it gives me this error:

Error C2338: Test writer must define specialization of ToString<const Q& q> for your class class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> > __cdecl Microsoft::VisualStudio::CppUnitTestFramework::ToString<class std::vector<struct Token,class std::allocator<struct Token> >>(const class std::vector<struct Token,class std::allocator<struct Token> > &).

My testing code is this:

#include <vector>

#include "pch.h"
#include "CppUnitTest.h"

#include "../calc-cli/token.hpp"


using namespace std;

using namespace Microsoft::VisualStudio::CppUnitTestFramework;


namespace test_tokens {
    TEST_CLASS(test_tokenize) {
    public:
        TEST_METHOD(binary_operation_plus) {
            auto r = tokenize("1+2");
            vector<Token> s = {
                Token{ Token_type::number, 1.0 },
                Token{ Token_type::plus },
                Token{ Token_type::number, 2.0}
            };

            Assert::AreEqual(r, s);
        }
    };
}

What's causing the error and how can I fix this?

1

There are 1 best solutions below

0
On

When you use Assert::AreEqual the framework wants to be able to display a string that describes the objects if the assert fails. It uses the templated function ToString for this, which includes specializations for all the basic data types. For any other data type, you would have to provide a specialization that knows how to format the data into a meaningful string.

The simplest solution is to use a different type of assert that doesn't require ToString. For example:

Assert::IsTrue(r == s, L"Some descriptive failure message");

The other option is to create the ToString specialization that the assert needs:

#include <CppUnitTestAssert.h>
namespace Microsoft {
    namespace VisualStudio {
        namespace CppUnitTestFramework {
            template<> static inline std::wstring ToString(const std::vector<Token> &t)
            {
                // Write some code here to create a descriptive std::wstring
                return std::wstring("My object description");
            }


        }
    }
}

I would only go to the trouble of making a specialization if I'm going to be writing a lot of tests using that same object type, and I want to automatically describe the objects.