Commits

Matt Oswald  committed 090cf4b

per-assert messages now use streaming operator, instead of being precomputed and passed into assert method

  • Participants
  • Parent commits 47c322f

Comments (0)

Files changed (19)

File Tests/UnitTests/Assert.Contains.cpp

     static const std::string msg = "xUnit++";
     std::vector<int> v;
 
-    auto assert = Assert.Throws<xUnitAssert>([&]() { Assert.Contains(v, 0, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([&]() { Assert.Contains(v, 0) << msg; });
     auto what = std::string(assert.what());
 
     Assert.NotEqual(std::string::npos, what.find(msg));
     static const std::string msg = "xUnit++";
     std::string actual = "abcd";
 
-    auto assert = Assert.Throws<xUnitAssert>([&]() { Assert.Contains(actual, "xyz", msg); });
+    auto assert = Assert.Throws<xUnitAssert>([&]() { Assert.Contains(actual, "xyz") << msg; });
     auto what = std::string(assert.what());
 
     Assert.NotEqual(std::string::npos, what.find(msg));

File Tests/UnitTests/Assert.DoesNotContain.cpp

     static const std::string msg = "xUnit++";
     std::vector<int> v(1, 0);
 
-    auto assert = Assert.Throws<xUnitAssert>([&]() { Assert.DoesNotContain(v, 0, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([&]() { Assert.DoesNotContain(v, 0) << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }
     static const std::string msg = "xUnit++";
     std::string actual = "abcd";
 
-    auto assert = Assert.Throws<xUnitAssert>([&]() { Assert.DoesNotContain(actual, "ab", msg); });
+    auto assert = Assert.Throws<xUnitAssert>([&]() { Assert.DoesNotContain(actual, "ab") << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Assert.DoesNotThrow.cpp

 
     try
     {
-        Assert.DoesNotThrow([=]() { throw std::exception(exceptionMessage.c_str()); }, userMessage);
+        Assert.DoesNotThrow([=]() { throw std::exception(exceptionMessage.c_str()); }) << userMessage;
     }
     catch(const xUnitAssert &assert)
     {

File Tests/UnitTests/Assert.Empty.cpp

     v.push_back(0);
     v.push_back(1);
 
-    auto assert = Assert.Throws<xUnitAssert>([&]() { Assert.Empty(v, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([&]() { Assert.Empty(v) << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Assert.Equal.cpp

 {
     static const std::string msg = "custom message";
 
-    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.Equal(0, 1, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.Equal(0, 1) << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Assert.Fail.cpp

 {
     static const std::string msg = "xUnit++";
 
-    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.Fail(msg); });
+    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.Fail() << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Assert.False.cpp

 {
     static const std::string msg = "xUnit++";
 
-    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.False(true, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.False(true) << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Assert.InRange.cpp

 {
     static const std::string msg = "xUnit++";
 
-    auto assert = Assert.Throws<xUnitAssert>([=]() { Assert.InRange(1, 0, 1, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([=]() { Assert.InRange(1, 0, 1) << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Assert.NotEqual.cpp

 {
     static const std::string msg = "custom message";
 
-    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.NotEqual(0, 0, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.NotEqual(0, 0) << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Assert.NotInRange.cpp

 {
     static const std::string msg = "xUnit++";
 
-    auto assert = Assert.Throws<xUnitAssert>([=]() { Assert.NotInRange(0, 0, 1, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([=]() { Assert.NotInRange(0, 0, 1) << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Assert.NotNull.cpp

 FACT(NotNullAppendsUserMessage)
 {
     static const std::string msg = "xUnit++";
-    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.NotNull(nullptr, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.NotNull(nullptr) << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Assert.NotSame.cpp

 
     int x;
 
-    auto assert = Assert.Throws<xUnitAssert>([&]() { Assert.NotSame(x, x, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([&]() { Assert.NotSame(x, x) << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Assert.Null.cpp

 {
     static const std::string msg = "xUnit++";
     int x;
-    auto assert = Assert.Throws<xUnitAssert>([=]() { Assert.Null(&x, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([=]() { Assert.Null(&x) << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Assert.Same.cpp

 {
     static const std::string msg = "xUnit++";
 
-    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.Same(0, 1, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.Same(0, 1) << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Assert.True.cpp

 {
     static const std::string msg = "xUnit++";
 
-    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.True(false, msg); });
+    auto assert = Assert.Throws<xUnitAssert>([]() { Assert.True(false) << msg; });
 
     Assert.Contains(assert.what(), msg.c_str());
 }

File Tests/UnitTests/Attributes.cpp

         }
     }
 
-    Assert.Fail("Could not find self in test list.");
+    Assert.Fail() << "Could not find self in test list.";
 }
 
 FACT(SkippedTestsShouldNotBeInstantiated)
     {
         SkippedTest()
         {
-            Assert.Fail("Should not be instantiated.");
+            Assert.Fail() << "Should not be instantiated.";
         }
     
         void RunTest()
         {
-            Assert.Fail("Should not be run.");
+            Assert.Fail() << "Should not be run.";
         }
     };
 

File Tests/UnitTests/Theory.cpp

 {
     attributes.insert(std::make_pair("Skip", "Testing skip."));
 
-    auto doTheory = [](int) { Assert.Fail("Should not be run."); };
+    auto doTheory = [](int) { Assert.Fail() << "Should not be run."; };
 
     xUnitpp::TestCollection::Register reg(collection, doTheory, RawFunctionProvider, "TheoriesGetAllDataPassedToThem", "Theory", attributes, -1, __FILE__, __LINE__);
 
         }
     }
 
-    Assert.Fail("Could not find self in test list.");
+    Assert.Fail() << "Could not find self in test list.";
 }
 
 std::vector<std::tuple<std::string, std::vector<std::tuple<int, std::string>>>> ComplexProvider()

File xUnit++/src/xUnitAssert.cpp

 
 namespace
 {
-    std::string AssembleWhat(const std::string &call, const std::string &userMsg, const std::string &customMsg,
+    std::string AssembleWhat(const std::string &call, const std::vector<std::string> &userMsg, const std::string &customMsg,
                              const std::string &expected, const std::string &actual)
     {
         std::string msg = "Assert." + call + "() failure";
         if (!userMsg.empty())
         {
-            msg += ": " + userMsg;
+            msg += ": ";
+            
+            for (const auto &s : userMsg)
+            {
+                msg += s;
+            }
 
             if (!customMsg.empty())
             {
 namespace xUnitpp
 {
 
-xUnitAssert::xUnitAssert(const std::string &call, const std::string &userMsg, const std::string &customMsg,
-                         const std::string &expected, const std::string &actual, const xUnitpp::LineInfo &lineInfo)
-    : base(AssembleWhat(call, userMsg, customMsg, expected, actual).c_str())
-    , lineInfo(lineInfo)
+const xUnitAssert &xUnitAssert::None()
+{
+    static xUnitAssert none("", LineInfo::empty());
+    return none;
+}
+
+xUnitAssert::xUnitAssert(const std::string &call, const xUnitpp::LineInfo &lineInfo)
+    : lineInfo(lineInfo)
+    , call(call + "() failure")
 {
 }
 
-xUnitAssert::xUnitAssert(const xUnitAssert &other)
-    : base(other.what())
-    , lineInfo(other.lineInfo)
+xUnitAssert &xUnitAssert::CustomMessage(const std::string &message)
 {
+    customMessage = message;
+    return *this;
+}
+
+xUnitAssert &xUnitAssert::Expected(const std::string &str)
+{
+    expected = str;
+    return *this;
+}
+
+xUnitAssert &xUnitAssert::Actual(const std::string &str)
+{
+    actual = str;
+    return *this;
 }
 
 const LineInfo &xUnitAssert::LineInfo() const
     return lineInfo;
 }
 
+const char *xUnitAssert::what() const
+{
+    if (whatMessage.empty())
+    {
+        whatMessage = AssembleWhat(call, userMessage, customMessage, expected, actual);
+    }
+
+    return whatMessage.c_str();
+}
+
+xUnitFailure::xUnitFailure()
+    : assert(xUnitAssert::None())
+    , refCount(*(new int(0)))
+    , failed(false)
+{
+}
+
+xUnitFailure::xUnitFailure(xUnitAssert assert)
+    : assert(assert)
+    , refCount(*(new int(1)))
+    , failed(true)
+{
+}
+
+xUnitFailure::xUnitFailure(const xUnitFailure &other)
+    : assert(other.assert)
+    , refCount(other.refCount)
+    , failed(other.failed)
+{
+    refCount++;
+}
+
+xUnitFailure::~xUnitFailure()
+{
+    if (!--refCount)
+    {
+        delete &refCount;
+
+        if (failed)
+        {
+            throw assert;
+        }
+    } 
+}
+
+xUnitFailure xUnitFailure::None()
+{
+    return xUnitFailure();
+}
+
+xUnitFailure Assert::OnSuccess() const
+{
+    return xUnitFailure::None();
+}
+
 double Assert::round(double value, size_t precision)
 {
     if (value < 0)
     }
 }
 
-void Assert::Equal(const std::string &expected, const std::string &actual, const std::string &msg, const LineInfo &lineInfo) const
+xUnitFailure Assert::Equal(const std::string &expected, const std::string &actual, const LineInfo &lineInfo) const
 {
     if (expected != actual)
     {
-        throw xUnitAssert("Equal", msg, "", expected, actual, lineInfo);
+        return OnFailure(xUnitAssert(callPrefix + "Equal", lineInfo)
+            .Expected(expected)
+            .Actual(actual));
     }
+
+    return OnSuccess();
 }
 
-void Assert::Equal(const std::string &expected, const std::string &actual, const LineInfo &lineInfo) const
+xUnitFailure Assert::Equal(const char *expected, const char *actual, const LineInfo &lineInfo) const
 {
-    Equal(expected, actual, std::string(""), lineInfo);
+    return Equal(std::string(expected), std::string(actual), lineInfo);
 }
 
-void Assert::Equal(const char *expected, const char *actual, const std::string &msg, const LineInfo &lineInfo) const
+xUnitFailure Assert::Equal(const std::string &expected, const char *actual, const LineInfo &lineInfo) const
 {
-    Equal(std::string(expected), std::string(actual), msg, lineInfo);
+    return Equal(expected, std::string(actual), lineInfo);
 }
 
-void Assert::Equal(const char *expected, const char *actual, const LineInfo &lineInfo) const
+xUnitFailure Assert::Equal(float expected, float actual, int precision, const LineInfo &lineInfo) const
 {
-    Equal(std::string(expected), std::string(actual), std::string(""), lineInfo);
+    return Equal((double)expected, (double)actual, precision, lineInfo);
 }
 
-void Assert::Equal(const std::string &expected, const char *actual, const std::string &msg, const LineInfo &lineInfo) const
-{
-    Equal(expected, std::string(actual), msg, lineInfo);
-}
-
-void Assert::Equal(const std::string &expected, const char *actual, const LineInfo &lineInfo) const
-{
-    Equal(expected, std::string(actual), std::string(""), lineInfo);
-}
-
-void Assert::Equal(float expected, float actual, int precision, const std::string &msg, const LineInfo &lineInfo) const
-{
-    Equal((double)expected, (double)actual, precision, msg, lineInfo);
-}
-
-void Assert::Equal(float expected, float actual, int precision, const LineInfo &lineInfo) const
-{
-    Equal(expected, actual, precision, "", lineInfo);
-}
-
-void Assert::Equal(double expected, double actual, int precision, const std::string &msg, const LineInfo &lineInfo) const
+xUnitFailure Assert::Equal(double expected, double actual, int precision, const LineInfo &lineInfo) const
 {
     auto er = round(expected, precision);
     auto ar = round(actual, precision);
 
-    Equal(er, ar, [](double er, double ar) { return er == ar; }, msg, lineInfo);
+    return Equal(er, ar, [](double er, double ar) { return er == ar; }, lineInfo);
 }
 
-void Assert::Equal(double expected, double actual, int precision, const LineInfo &lineInfo) const
+xUnitFailure Assert::Fail(const LineInfo &lineInfo) const
 {
-    Equal(expected, actual, precision, "", lineInfo);
+    return OnFailure(xUnitAssert(callPrefix + "Fail", lineInfo));
 }
 
-void Assert::Fail(const std::string &msg, const LineInfo &lineInfo) const
-{
-    throw xUnitAssert("Fail", msg, "", "", "", lineInfo);
-}
-
-void Assert::Fail(const LineInfo &lineInfo) const
-{
-    Fail("", lineInfo);
-}
-
-void Assert::False(bool b, const std::string &msg, const LineInfo &lineInfo) const
+xUnitFailure Assert::False(bool b, const LineInfo &lineInfo) const
 {
     if (b)
     {
-        throw xUnitAssert("False", msg, "", "false", "true", lineInfo);
+        return OnFailure(xUnitAssert(callPrefix + "False", lineInfo).Expected("false").Actual("true"));
     }
+
+    return OnSuccess();
 }
 
-void Assert::False(bool b, const LineInfo &lineInfo) const
-{
-    False(b, "", lineInfo);
-}
-
-void Assert::True(bool b, const std::string &msg, const LineInfo &lineInfo) const
+xUnitFailure Assert::True(bool b, const LineInfo &lineInfo) const
 {
     if (!b)
     {
-        throw xUnitAssert("True", msg, "", "true", "false", lineInfo);
+        return OnFailure(xUnitAssert(callPrefix + "True", lineInfo).Expected("true").Actual("false"));
     }
+
+    return OnSuccess();
 }
 
-void Assert::True(bool b, const LineInfo &lineInfo) const
+xUnitFailure Assert::DoesNotContain(const char *actualString, const char *value, const LineInfo &lineInfo) const
 {
-    True(b, "", lineInfo);
+    return DoesNotContain(std::string(actualString), std::string(value), lineInfo);
 }
 
-void Assert::DoesNotContain(const char *actualString, const char *value, const std::string &msg, const LineInfo &lineInfo) const
+xUnitFailure Assert::DoesNotContain(const std::string &actualString, const char *value, const LineInfo &lineInfo) const
 {
-    DoesNotContain(std::string(actualString), std::string(value), msg, lineInfo);
+    return DoesNotContain(actualString, std::string(value), lineInfo);
 }
 
-void Assert::DoesNotContain(const char *actualString, const char *value, const LineInfo &lineInfo) const
-{
-    DoesNotContain(actualString, value, "", lineInfo);
-}
-
-void Assert::DoesNotContain(const std::string &actualString, const char *value, const std::string &msg, const LineInfo &lineInfo) const
-{
-    DoesNotContain(actualString, std::string(value), msg, lineInfo);
-}
-
-void Assert::DoesNotContain(const std::string &actualString, const char *value, const LineInfo &lineInfo) const
-{
-    DoesNotContain(actualString, value, "", lineInfo);
-}
-
-void Assert::DoesNotContain(const std::string &actualString, const std::string &value, const std::string &msg, const LineInfo &lineInfo) const
+xUnitFailure Assert::DoesNotContain(const std::string &actualString, const std::string &value, const LineInfo &lineInfo) const
 {
     auto found = actualString.find(value);
     if (found != std::string::npos)
     {
-        throw xUnitAssert("DoesNotContain", msg, "Found: \"" + value + "\" at position " + std::to_string(found) + ".", "", "", lineInfo);
+        return OnFailure(xUnitAssert(callPrefix + "DoesNotContain", lineInfo).CustomMessage("Found: \"" + value + "\" at position " + std::to_string(found) + "."));
     }
+
+    return OnSuccess();
 }
 
-void Assert::DoesNotContain(const std::string &actualString, const std::string &value, const LineInfo &lineInfo) const
+xUnitFailure Assert::Contains(const char *actualString, const char *value, const LineInfo &lineInfo) const
 {
-    DoesNotContain(actualString, value, "", lineInfo);
+    return Contains(std::string(actualString), std::string(value), lineInfo);
 }
 
-void Assert::Contains(const char *actualString, const char *value, const std::string &msg, const LineInfo &lineInfo) const
+xUnitFailure Assert::Contains(const std::string &actualString, const char *value, const LineInfo &lineInfo) const
 {
-    Contains(std::string(actualString), std::string(value), msg, lineInfo);
+    return Contains(actualString, std::string(value), lineInfo);
 }
 
-void Assert::Contains(const char *actualString, const char *value, const LineInfo &lineInfo) const
-{
-    Contains(actualString, value, "", lineInfo);
-}
-
-void Assert::Contains(const std::string &actualString, const char *value, const std::string &msg, const LineInfo &lineInfo) const
-{
-    Contains(actualString, std::string(value), msg, lineInfo);
-}
-
-void Assert::Contains(const std::string &actualString, const char *value, const LineInfo &lineInfo) const
-{
-    Contains(actualString, value, "", lineInfo);
-}
-
-void Assert::Contains(const std::string &actualString, const std::string &value, const std::string &msg, const LineInfo &lineInfo) const
+xUnitFailure Assert::Contains(const std::string &actualString, const std::string &value, const LineInfo &lineInfo) const
 {
     if (actualString.find(value) == std::string::npos)
     {
-        throw xUnitAssert("Contains", msg, "", actualString, value, lineInfo);
+        return OnFailure(xUnitAssert(callPrefix + "Contains", lineInfo).Expected(actualString).Actual(value));
     }
-}
 
-void Assert::Contains(const std::string &actualString, const std::string &value, const LineInfo &lineInfo) const
-{
-    Contains(actualString, value, "", lineInfo);
+    return OnSuccess();
 }
 
 }

File xUnit++/xUnit++/xUnitAssert.h

 
 #include <algorithm>
 #include <exception>
+#include <functional>
+#include <sstream>
 #include <string>
 #include <type_traits>
+#include <vector>
 #include "LineInfo.h"
 
 namespace xUnitpp
     typedef std::exception base;
 
 public:
-    xUnitAssert(const std::string &call, const std::string &userMsg, const std::string &customMsg,
-                const std::string &expected, const std::string &actual, const LineInfo &lineInfo);
-    xUnitAssert(const xUnitAssert &other);
+    xUnitAssert(const std::string &call, const LineInfo &lineInfo);
+
+    xUnitAssert &CustomMessage(const std::string &message);
+    xUnitAssert &Expected(const std::string &expected);
+    xUnitAssert &Actual(const std::string &actual);
+
+    template<typename T>
+    xUnitAssert &AppendUserMessage(const T &value)
+    {
+        std::stringstream str;
+        str << value;
+        userMessage.push_back(str.str());
+
+        return *this;
+    }
 
     const LineInfo &LineInfo() const;
 
+    static const xUnitAssert &None();
+
+    virtual const char *what() const override;
+
 private:
     xUnitpp::LineInfo lineInfo;
+    std::string call;
+    std::string customMessage;
+    std::string expected;
+    std::string actual;
+    std::vector<std::string> userMessage;
+
+    mutable std::string whatMessage;
 };
 
-const class Assert
+class xUnitFailure
 {
 private:
+    xUnitFailure();
+
+public:
+    xUnitFailure(xUnitAssert assert);
+    xUnitFailure(const xUnitFailure &other);
+    ~xUnitFailure();
+
+    static xUnitFailure None();
+
+    template<typename T>
+    xUnitFailure &operator <<(const T &value)
+    {
+        if (failed)
+        {
+            assert.AppendUserMessage(value);
+        }
+
+        return *this;
+    }
+
+private:
+    xUnitFailure &operator =(xUnitFailure other);
+
+protected:
+    xUnitAssert assert;
+    int &refCount;
+    bool failed;
+};
+
+class Assert
+{
+protected:
     static double round(double value, size_t precision);
 
     template<typename T>
         static const bool value = (sizeof(f<T>(nullptr)) == sizeof(char));
     };
 
+    std::string callPrefix;
+    std::function<xUnitFailure(xUnitAssert)> OnFailure;
+
+    xUnitFailure OnSuccess() const;
+
 public:
     template<typename TExpected, typename TActual, typename TComparer>
-    void Equal(TExpected expected, TActual actual, TComparer comparer, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
+    xUnitFailure Equal(TExpected expected, TActual actual, TComparer comparer, const LineInfo &lineInfo = LineInfo::empty()) const
     {
         using namespace std;
 
         if (!comparer(expected, actual))
         {
-            throw xUnitAssert("Equal", msg, "", to_string(expected), to_string(actual), lineInfo);
+            return OnFailure(xUnitAssert(callPrefix + "Equal", lineInfo).Expected(to_string(expected)).Actual(to_string(actual)));
         }
-    }
 
-    template<typename TExpected, typename TActual, typename TComparer>
-    void Equal(TExpected expected, TActual actual, TComparer comparer, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        Equal(expected, actual, comparer, "", lineInfo);
+        return OnSuccess();
     }
 
     template<typename TExpected, typename TActual>
-    void Equal(TExpected expected, TActual actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
+    xUnitFailure Equal(TExpected expected, TActual actual, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        Equal(expected, actual, [](TExpected expected, TActual actual) { return expected == actual; }, msg, lineInfo);
+        return Equal(expected, actual, [](TExpected expected, TActual actual) { return expected == actual; }, lineInfo);
     }
 
-    template<typename TExpected, typename TActual>
-    void Equal(TExpected expected, TActual actual, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        Equal(expected, actual, std::string(""), lineInfo);
-    }
-
-    void Equal(const char *expected, const char *actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void Equal(const char *expected, const char *actual, const LineInfo &lineInfo = LineInfo::empty()) const;
-
-    void Equal(const std::string &expected, const char *actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void Equal(const std::string &expected, const char *actual, const LineInfo &lineInfo = LineInfo::empty()) const;
-
-    void Equal(const std::string &expected, const std::string &actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void Equal(const std::string &expected, const std::string &actual, const LineInfo &lineInfo = LineInfo::empty()) const;
-
-    void Equal(float expected, float actual, int precision, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void Equal(float expected, float actual, int precision, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void Equal(double expected, double actual, int precision, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void Equal(double expected, double actual, int precision, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
+    xUnitFailure Equal(const char *expected, const char *actual, const LineInfo &lineInfo = LineInfo::empty()) const;
+    xUnitFailure Equal(const std::string &expected, const char *actual, const LineInfo &lineInfo = LineInfo::empty()) const;
+    xUnitFailure Equal(const std::string &expected, const std::string &actual, const LineInfo &lineInfo = LineInfo::empty()) const;
+    xUnitFailure Equal(float expected, float actual, int precision, const LineInfo &lineInfo = LineInfo::empty()) const;
+    xUnitFailure Equal(double expected, double actual, int precision, const LineInfo &lineInfo = LineInfo::empty()) const;
 
     template<typename TExpected, typename TActual, typename TComparer>
-    void Equal(const TExpected &expectedBegin, const TExpected &expectedEnd, const TActual &actualBegin, const TActual &actualEnd, TComparer comparer, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
+    xUnitFailure Equal(const TExpected &expectedBegin, const TExpected &expectedEnd, const TActual &actualBegin, const TActual &actualEnd, TComparer comparer, const LineInfo &lineInfo = LineInfo::empty()) const
     {
         auto expected = expectedBegin;
         auto actual = actualBegin;
 
         if (expected != expectedEnd || actual != actualEnd)
         {
-            throw xUnitAssert("Equal", msg,
-                "Sequence unequal at location " + std::to_string(index) + ".",
-                RangeToString(expectedBegin, expectedEnd),
-                RangeToString(actualBegin, actualEnd),
-                lineInfo);
+            return OnFailure(xUnitAssert(callPrefix + "Equal", lineInfo)
+                .CustomMessage("Sequence unequal at location " + std::to_string(index) + ".")
+                .Expected(RangeToString(expectedBegin, expectedEnd))
+                .Actual(RangeToString(actualBegin, actualEnd)));
         }
+
+        return OnSuccess();
+    }
+
+    template<typename TExpected, typename TActual>
+    xUnitFailure Equal(const TExpected &expectedBegin, const TExpected &expectedEnd, const TActual &actualBegin, const TActual &actualEnd, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        return Equal(expectedBegin, expectedEnd, actualBegin, actualEnd, [](decltype(*expectedBegin) a, decltype(*actualBegin) b) { return a == b; }, lineInfo);
     }
 
     template<typename TExpected, typename TActual, typename TComparer>
-    void Equal(const TExpected &expectedBegin, const TExpected &expectedEnd, const TActual &actualBegin, const TActual &actualEnd, TComparer comparer, const LineInfo &lineInfo = LineInfo::empty()) const
+    xUnitFailure NotEqual(TExpected expected, TActual actual, TComparer comparer, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        Equal(expectedBegin, expectedEnd, actualBegin, actualEnd, comparer, "", lineInfo);
+        if (comparer(expected, actual))
+        {
+            return OnFailure(xUnitAssert(callPrefix + "NotEqual", lineInfo));
+        }
+
+        return OnSuccess();
     }
 
     template<typename TExpected, typename TActual>
-    void Equal(const TExpected &expectedBegin, const TExpected &expectedEnd, const TActual &actualBegin, const TActual &actualEnd, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
+    xUnitFailure NotEqual(TExpected expected, TActual actual, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        Equal(expectedBegin, expectedEnd, actualBegin, actualEnd, [](decltype(*expectedBegin) a, decltype(*actualBegin) b) { return a == b; }, msg, lineInfo);
-    }
-
-    template<typename TExpected, typename TActual>
-    void Equal(const TExpected &expectedBegin, const TExpected &expectedEnd, const TActual &actualBegin, const TActual &actualEnd, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        Equal(expectedBegin, expectedEnd, actualBegin, actualEnd, std::string(""), lineInfo);
+        return NotEqual(expected, actual, [](TExpected expected, TActual actual) { return expected == actual; }, lineInfo);
     }
 
     template<typename TExpected, typename TActual, typename TComparer>
-    void NotEqual(TExpected expected, TActual actual, TComparer comparer, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        if (comparer(expected, actual))
-        {
-            throw xUnitAssert("NotEqual", msg, "", "", "", lineInfo);
-        }
-    }
-
-    template<typename TExpected, typename TActual, typename TComparer>
-    void NotEqual(TExpected expected, TActual actual, TComparer comparer, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        NotEqual(expected, actual, comparer, "", lineInfo);
-    }
-
-    template<typename TExpected, typename TActual>
-    void NotEqual(TExpected expected, TActual actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        NotEqual(expected, actual, [](TExpected expected, TActual actual) { return expected == actual; }, msg, lineInfo);
-    }
-
-    template<typename TExpected, typename TActual>
-    void NotEqual(TExpected expected, TActual actual, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        NotEqual(expected, actual, std::string(""), lineInfo);
-    }
-
-    template<typename TExpected, typename TActual, typename TComparer>
-    void NotEqual(const TExpected &expectedBegin, const TExpected &expectedEnd, const TActual &actualBegin, const TActual &actualEnd, TComparer comparer, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
+    xUnitFailure NotEqual(const TExpected &expectedBegin, const TExpected &expectedEnd, const TActual &actualBegin, const TActual &actualEnd, TComparer comparer, const LineInfo &lineInfo = LineInfo::empty()) const
     {
         auto expected = expectedBegin;
         auto actual = actualBegin;
         {
             if (!comparer(*expected, *actual))
             {
-                return;
+                break;
             }
 
             ++expected;
 
         if (expected == expectedEnd && actual == actualEnd)
         {
-            throw xUnitAssert("NotEqual", msg, "", "", "", lineInfo);
+            return OnFailure(xUnitAssert(callPrefix + "NotEqual", lineInfo));
         }
-    }
 
-    template<typename TExpected, typename TActual, typename TComparer>
-    void NotEqual(const TExpected &expectedBegin, const TExpected &expectedEnd, const TActual &actualBegin, const TActual &actualEnd, TComparer comparer, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        NotEqual(expectedBegin, expectedEnd, actualBegin, actualEnd, comparer, "", lineInfo);
+        return OnSuccess();
     }
 
     template<typename TExpected, typename TActual>
-    void NotEqual(const TExpected &expectedBegin, const TExpected &expectedEnd, const TActual &actualBegin, const TActual &actualEnd, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
+    xUnitFailure NotEqual(const TExpected &expectedBegin, const TExpected &expectedEnd, const TActual &actualBegin, const TActual &actualEnd, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        NotEqual(expectedBegin, expectedEnd, actualBegin, actualEnd, [](decltype(*expectedBegin) a, decltype(*actualBegin) b) { return a == b; }, msg, lineInfo);
+        return NotEqual(expectedBegin, expectedEnd, actualBegin, actualEnd, [](decltype(*expectedBegin) a, decltype(*actualBegin) b) { return a == b; }, lineInfo);
     }
 
-    template<typename TExpected, typename TActual>
-    void NotEqual(const TExpected &expectedBegin, const TExpected &expectedEnd, const TActual &actualBegin, const TActual &actualEnd, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        NotEqual(expectedBegin, expectedEnd, actualBegin, actualEnd, std::string(""), lineInfo);
-    }
 
     template<typename TFunc>
-    void DoesNotThrow(TFunc &&fn, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
+    xUnitFailure DoesNotThrow(TFunc &&fn, const LineInfo &lineInfo = LineInfo::empty()) const
     {
         try
         {
         }
         catch (const std::exception &e)
         {
-            throw xUnitAssert("DoesNotThrow", msg, "", "(no exception)", e.what(), lineInfo);
+            return OnFailure(xUnitAssert(callPrefix + "DoesNotThrow", lineInfo)
+                .Expected("(no exception)")
+                .Actual(e.what()));
         }
         catch (...)
         {
-            throw xUnitAssert("DoesNotThrow", msg, "", "(no exception)", "Crash: unknown exception.", lineInfo);
+            return OnFailure(xUnitAssert(callPrefix + "DoesNotThrow", lineInfo)
+                .Expected("(no exception)")
+                .Actual("Crash: unknown exception."));
         }
+
+        return OnSuccess();
     }
 
-    template<typename TFunc>
-    void DoesNotThrow(TFunc &&fn, const LineInfo &lineInfo = LineInfo::empty()) const
+    xUnitFailure Fail(const LineInfo &lineInfo = LineInfo::empty()) const;
+
+    xUnitFailure False(bool b, const LineInfo &lineInfo = LineInfo::empty()) const;
+
+    xUnitFailure True(bool b, const LineInfo &lineInfo = LineInfo::empty()) const;
+
+    template<typename TSequence>
+    typename std::enable_if<has_empty<TSequence>::value, xUnitFailure>::type Empty(const TSequence &sequence, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        DoesNotThrow(fn, "", lineInfo);
+        if (!sequence.empty())
+        {
+            return OnFailure(xUnitAssert(callPrefix + "Empty", lineInfo));
+        }
+
+        return OnSuccess();
     }
 
+    template<typename TSequence>
+    typename std::enable_if<!has_empty<TSequence>::value, xUnitFailure>::type Empty(const TSequence &sequence, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        using namespace std;
+    
+        if (begin(sequence) != end(sequence))
+        {
+            return OnFailure(xUnitAssert(callPrefix + "Empty", lineInfo));
+        }
+
+        return OnSuccess();
+    }
+
+    template<typename TSequence, typename TPredicate>
+    xUnitFailure DoesNotContainPred(const TSequence &sequence, TPredicate &&predicate, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        using namespace std;
+
+        auto found = find_if(begin(sequence), end(sequence), predicate);
+        if (found != end(sequence))
+        {
+            return OnFailure(xUnitAssert(callPrefix + "DoesNotContain", lineInfo)
+                .CustomMessage("Found: matching value at position " + to_string(distance(begin(sequence), found)) + "."));
+        }
+
+        return OnSuccess();
+    }
+
+    template<typename TSequence, typename T>
+    xUnitFailure DoesNotContain(const TSequence &sequence, T value, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        return DoesNotContainPred(sequence, [&value](const T& actual) { return actual == value; }, lineInfo);
+    }
+
+    xUnitFailure DoesNotContain(const char *actualString, const char *value, const LineInfo &lineInfo = LineInfo::empty()) const;
+    xUnitFailure DoesNotContain(const std::string &actualString, const char *value, const LineInfo &lineInfo = LineInfo::empty()) const;
+    xUnitFailure DoesNotContain(const std::string &actualString, const std::string &value, const LineInfo &lineInfo = LineInfo::empty()) const;
+
+    template<typename TSequence, typename TPredicate>
+    xUnitFailure ContainsPred(const TSequence &sequence, TPredicate &&predicate, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        using namespace std;
+
+        if (find_if(begin(sequence), end(sequence), predicate) == end(sequence))
+        {
+            return OnFailure(xUnitAssert(callPrefix + "Contains", lineInfo));
+        }
+
+        return OnSuccess();
+    }
+
+    template<typename TSequence, typename T>
+    xUnitFailure Contains(const TSequence &sequence, T value, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        return ContainsPred(sequence, [&value](const T &actual) { return actual == value; }, lineInfo); 
+    }
+
+    xUnitFailure Contains(const char *actualString, const char *value, const LineInfo &lineInfo = LineInfo::empty()) const;
+    xUnitFailure Contains(const std::string &actualString, const char *value, const LineInfo &lineInfo = LineInfo::empty()) const;
+    xUnitFailure Contains(const std::string &actualString, const std::string &value, const LineInfo &lineInfo = LineInfo::empty()) const;
+
+    template<typename TActual, typename TRange>
+    xUnitFailure InRange(TActual actual, TRange min, TRange max, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        if (min >= max)
+        {
+            throw std::invalid_argument("Assert.InRange argument error: min (" + std::to_string(min) + ") must be strictly less than max (" + std::to_string(max) + ").");
+        }
+
+        if (actual < min || actual >= max)
+        {
+            return OnFailure(xUnitAssert(callPrefix + "InRange", lineInfo)
+                .Expected("[" + std::to_string(min) + " - " + std::to_string(max) + ")")
+                .Actual(std::to_string(actual)));
+        }
+
+        return OnSuccess();
+    }
+
+    template<typename TActual, typename TRange>
+    xUnitFailure NotInRange(TActual actual, TRange min, TRange max, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        if (min >= max)
+        {
+            throw std::invalid_argument("Assert.NotInRange argument error: min (" + std::to_string(min) + ") must be strictly less than max (" + std::to_string(max) + ").");
+        }
+
+        if (actual >= min && actual < max)
+        {
+            return OnFailure(xUnitAssert(callPrefix + "NotInRange", lineInfo)
+                .Expected("[" + std::to_string(min) + " - " + std::to_string(max) + ")")
+                .Actual(std::to_string(actual)));
+        }
+
+        return OnSuccess();
+    }
+
+    template<typename T>
+    xUnitFailure NotNull(const T &value, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        if (value == nullptr)
+        {
+            return OnFailure(xUnitAssert(callPrefix + "NotNull", lineInfo));
+        }
+
+        return OnSuccess();
+    }
+
+    template<typename T>
+    xUnitFailure Null(const T &value, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        if (value != nullptr)
+        {
+            return OnFailure(xUnitAssert(callPrefix + "Null", lineInfo));
+        }
+
+        return OnSuccess();
+    }
+
+    template<typename T>
+    xUnitFailure NotSame(const T &expected, const T &actual, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        if (&expected == &actual)
+        {
+            return OnFailure(xUnitAssert(callPrefix + "NotSame", lineInfo));
+        }
+
+        return OnSuccess();
+    }
+
+
+    template<typename T>
+    xUnitFailure NotSame(const T *expected, const T *actual, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        if (expected == actual)
+        {
+            return OnFailure(xUnitAssert(callPrefix + "NotSame", lineInfo));
+        }
+
+        return OnSuccess();
+    }
+
+    template<typename T>
+    xUnitFailure NotSame(T *expected, T *actual, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        if (expected == actual)
+        {
+            return OnFailure(xUnitAssert(callPrefix + "NotSame", lineInfo));
+        }
+
+        return OnSuccess();
+    }
+
+    template<typename T>
+    xUnitFailure Same(const T &expected, const T &actual, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        if (&expected != &actual)
+        {
+            return OnFailure(xUnitAssert(callPrefix + "Same", lineInfo));
+        }
+
+        return OnSuccess();
+    }
+
+    template<typename T>
+    xUnitFailure Same(T *expected, T *actual, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        if (expected != actual)
+        {
+            return OnFailure(xUnitAssert("Same", lineInfo));
+        }
+
+        return OnSuccess();
+    }
+
+    template<typename T>
+    xUnitFailure Same(const T *expected, const T *actual, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        if (expected != actual)
+        {
+            return OnFailure(xUnitAssert("Same", lineInfo));
+        }
+
+        return OnSuccess();
+    }
+
+    Assert(const std::string &callPrefix = "Assert.")
+        : callPrefix(callPrefix)
+        , OnFailure([](xUnitAssert assert) { return xUnitFailure(assert); })
+    {
+    }
+};
+
+const class : public Assert
+{
+public:
     template<typename TException, typename TFunc>
     TException Throws(TFunc &&fn, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
     {
         }
         catch (const std::exception &e)
         {
-            throw xUnitAssert("Throws", msg, "", typeid(TException).name(), e.what(), lineInfo);
+            throw xUnitAssert(callPrefix + "Throws", lineInfo)
+                .Expected(typeid(TException).name())
+                .Actual(e.what())
+                .AppendUserMessage(msg);
         }
         catch (...)
         {
-            throw xUnitAssert("Throws", msg, "", typeid(TException).name(), "Crash: unknown exception.", lineInfo);
+            throw xUnitAssert(callPrefix + "Throws", lineInfo)
+                .Expected(typeid(TException).name())
+                .Actual("Crash: unknown exception.")
+                .AppendUserMessage(msg);
         }
 
-        throw xUnitAssert("Throws", msg, "", typeid(TException).name(), "No exception.", lineInfo);
+        throw xUnitAssert(callPrefix + "Throws", lineInfo)
+            .Expected(typeid(TException).name())
+            .Actual("No exception.")
+            .AppendUserMessage(msg);
     }
 
     template<typename TException, typename TFunc>
     {
         return Throws<TException>(fn, "", lineInfo);
     }
-
-    void Fail(const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void Fail(const LineInfo &lineInfo = LineInfo::empty()) const;
-
-    void False(bool b, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void False(bool b, const LineInfo &lineInfo = LineInfo::empty()) const;
-
-    void True(bool b, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void True(bool b, const LineInfo &lineInfo = LineInfo::empty()) const;
-
-    template<typename TSequence>
-    typename std::enable_if<has_empty<TSequence>::value>::type Empty(const TSequence &sequence, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        if (!sequence.empty())
-        {
-            throw xUnitAssert("Empty", msg, "", "", "", lineInfo);
-        }
-    }
-
-    template<typename TSequence>
-    typename std::enable_if<has_empty<TSequence>::value>::type Empty(const TSequence &sequence, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        Empty(sequence, "", lineInfo);
-    }
-
-    template<typename TSequence>
-    typename std::enable_if<!has_empty<TSequence>::value>::type Empty(const TSequence &sequence, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        using namespace std;
-    
-        if (begin(sequence) != end(sequence))
-        {
-            throw xUnitAssert("Empty", msg, "", "", "", lineInfo);
-        }
-    }
-
-    template<typename TSequence>
-    typename std::enable_if<!has_empty<TSequence>::value>::type Empty(const TSequence &sequence, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        Empty(sequence, "", lineInfo);
-    }
-
-    template<typename TSequence, typename TPredicate>
-    void DoesNotContainPred(const TSequence &sequence, TPredicate &&predicate, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        using namespace std;
-
-        auto found = find_if(begin(sequence), end(sequence), predicate);
-        if (found != end(sequence))
-        {
-            throw xUnitAssert("DoesNotContain", msg, "Found: matching value at position " + to_string(distance(begin(sequence), found)) + ".", "", "", lineInfo);
-        }
-    }
-
-    template<typename TSequence, typename TPredicate>
-    void DoesNotContainPred(const TSequence &sequence, TPredicate &&predicate, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        DoesNotContainPred(sequence, predicate, "", lineInfo);
-    }
-
-    template<typename TSequence, typename T>
-    void DoesNotContain(const TSequence &sequence, T value, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        DoesNotContainPred(sequence, [&value](const T& actual) { return actual == value; }, msg, lineInfo);
-    }
-
-    template<typename TSequence, typename T>
-    void DoesNotContain(const TSequence &sequence, T value, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        DoesNotContain(sequence, value, "", lineInfo);
-    }
-
-    void DoesNotContain(const char *actualString, const char *value, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void DoesNotContain(const char *actualString, const char *value, const LineInfo &lineInfo = LineInfo::empty()) const;
-
-    void DoesNotContain(const std::string &actualString, const char *value, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void DoesNotContain(const std::string &actualString, const char *value, const LineInfo &lineInfo = LineInfo::empty()) const;
-
-    void DoesNotContain(const std::string &actualString, const std::string &value, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void DoesNotContain(const std::string &actualString, const std::string &value, const LineInfo &lineInfo = LineInfo::empty()) const;
-
-    template<typename TSequence, typename TPredicate>
-    void ContainsPred(const TSequence &sequence, TPredicate &&predicate, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        using namespace std;
-
-        if (find_if(begin(sequence), end(sequence), predicate) == end(sequence))
-        {
-            throw xUnitAssert("Contains", msg, "", "", "", lineInfo);
-        }
-    }
-
-    template<typename TSequence, typename TPredicate>
-    void ContainsPred(const TSequence &sequence, TPredicate &&predicate, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        ContainsPred(sequence, predicate, "", lineInfo);
-    }
-
-    template<typename TSequence, typename T>
-    void Contains(const TSequence &sequence, T value, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        ContainsPred(sequence, [&value](const T &actual) { return actual == value; }, msg, lineInfo); 
-    }
-
-    template<typename TSequence, typename T>
-    void Contains(const TSequence &sequence, T value, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        Contains(sequence, value, "", lineInfo);
-    }
-
-    void Contains(const char *actualString, const char *value, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void Contains(const char *actualString, const char *value, const LineInfo &lineInfo = LineInfo::empty()) const;
-
-    void Contains(const std::string &actualString, const char *value, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void Contains(const std::string &actualString, const char *value, const LineInfo &lineInfo = LineInfo::empty()) const;
-
-    void Contains(const std::string &actualString, const std::string &value, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
-    void Contains(const std::string &actualString, const std::string &value, const LineInfo &lineInfo = LineInfo::empty()) const;
-
-    template<typename TActual, typename TRange>
-    void InRange(TActual actual, TRange min, TRange max, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        if (min >= max)
-        {
-            throw std::invalid_argument("Assert.InRange argument error: min (" + std::to_string(min) + ") must be strictly less than max (" + std::to_string(max) + ").");
-        }
-
-        if (actual < min || actual >= max)
-        {
-            throw xUnitAssert("InRange", msg, "", "[" + std::to_string(min) + " - " + std::to_string(max) + ")", std::to_string(actual), lineInfo);
-        }
-    }
-
-    template<typename TActual, typename TRange>
-    void InRange(TActual actual, TRange min, TRange max, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        InRange(actual, min, max, "", lineInfo);
-    }
-
-    template<typename TActual, typename TRange>
-    void NotInRange(TActual actual, TRange min, TRange max, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        if (min >= max)
-        {
-            throw std::invalid_argument("Assert.NotInRange argument error: min (" + std::to_string(min) + ") must be strictly less than max (" + std::to_string(max) + ").");
-        }
-
-        if (actual >= min && actual < max)
-        {
-            throw xUnitAssert("NotInRange", msg, "", "[" + std::to_string(min) + " - " + std::to_string(max) + ")", std::to_string(actual), lineInfo);
-        }
-    }
-
-    template<typename TActual, typename TRange>
-    void NotInRange(TActual actual, TRange min, TRange max, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        NotInRange(actual, min, max, "", lineInfo);
-    }
-
-    template<typename T>
-    void NotNull(const T &value, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        if (value == nullptr)
-        {
-            throw xUnitAssert("NotNull", msg, "", "", "", lineInfo);
-        }
-    }
-
-    template<typename T>
-    void NotNull(const T &value, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        NotNull(value, "", lineInfo);
-    }
-
-    template<typename T>
-    void Null(const T &value, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        if (value != nullptr)
-        {
-            throw xUnitAssert("Null", msg, "", "", "", lineInfo);
-        }
-    }
-
-    template<typename T>
-    void Null(const T &value, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        Null(value, "", lineInfo);
-    }
-
-    template<typename T>
-    void NotSame(const T &expected, const T &actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        if (&expected == &actual)
-        {
-            throw xUnitAssert("NotSame", msg, "", "", "", lineInfo);
-        }
-    }
-
-    template<typename T>
-    void NotSame(const T &expected, const T &actual, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        NotSame(expected, actual, "", lineInfo);
-    }
-
-    template<typename T>
-    void NotSame(const T *expected, const T *actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        if (expected == actual)
-        {
-            throw xUnitAssert("NotSame", msg, "", "", "", lineInfo);
-        }
-    }
-
-    template<typename T>
-    void NotSame(T *expected, T *actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        if (expected == actual)
-        {
-            throw xUnitAssert("NotSame", msg, "", "", "", lineInfo);
-        }
-    }
-
-    template<typename T>
-    void NotSame(T *expected, T *actual, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        NotSame(expected, actual, "", lineInfo);
-    }
-
-    template<typename T>
-    void NotSame(const T *expected, const T *actual, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        NotSame(expected, actual, "", lineInfo);
-    }
-
-    template<typename T>
-    void Same(const T &expected, const T &actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        if (&expected != &actual)
-        {
-            throw xUnitAssert("Same", msg, "", "", "", lineInfo);
-        }
-    }
-
-    template<typename T>
-    void Same(const T &expected, const T &actual, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        Same(expected, actual, "", lineInfo);
-    }
-
-    template<typename T>
-    void Same(T *expected, T *actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        if (expected != actual)
-        {
-            throw xUnitAssert("Same", msg, "", "", "", lineInfo);
-        }
-    }
-
-    template<typename T>
-    void Same(T *expected, T *actual, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        Same(expected, actual, "", lineInfo);
-    }
-
-    template<typename T>
-    void Same(const T *expected, const T *actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        if (expected != actual)
-        {
-            throw xUnitAssert("Same", msg, "", "", "", lineInfo);
-        }
-    }
-
-    template<typename T>
-    void Same(const T *expected, const T *actual, const LineInfo &lineInfo = LineInfo::empty()) const
-    {
-        Same(expected, actual, "", lineInfo);
-    }
 } Assert;
 
 }