Commits

Matt Oswald committed d188f6a

users can choose to pass a LineInfo object to their Assert calls, so any failing asserts are called out in the results instead of the test

Comments (0)

Files changed (20)

Tests/Attributes.cpp

         {
         }
 
-        virtual void ReportFailure(const xUnitpp::TestDetails &, int, const std::string &) override
+        virtual void ReportFailure(const xUnitpp::TestDetails &, int, const std::string &, const xUnitpp::LineInfo &) override
         {
         }
 

Tests/LineInfo.cpp

+#include "xUnit++.h"
+#include "IOutput.h"
+
+using xUnitpp::Assert;
+
+SUITE(LineInfo)
+{
+
+FACT(LineInfoOverridesDefaultTestLineInfo)
+{
+    auto file = "filename";
+    auto line = 1;
+    auto test = [=]() { Assert.Fail(xUnitpp::LineInfo(file, line)); };
+
+    struct EmptyReporter : xUnitpp::IOutput
+    {
+        EmptyReporter(const std::string &file, int line)
+            : file(file)
+            , line(line)
+        {
+        }
+
+        virtual void ReportStart(const xUnitpp::TestDetails &, int) override
+        {
+        }
+
+        virtual void ReportFailure(const xUnitpp::TestDetails &, int, const std::string &, const xUnitpp::LineInfo &lineInfo) override
+        {
+            Assert.Equal(file, lineInfo.file);
+            Assert.Equal(line, lineInfo.line);
+        }
+
+        virtual void ReportSkip(const xUnitpp::TestDetails &, const std::string &) override
+        {
+        }
+
+        virtual void ReportFinish(const xUnitpp::TestDetails &, int, xUnitpp::Duration) override
+        {
+        }
+
+        virtual void ReportAllTestsComplete(size_t, size_t, size_t, xUnitpp::Duration) override 
+        {
+        }
+
+    private:
+        std::string file;
+        int line;
+    } emptyReporter(file, line);
+
+
+    xUnitpp::AttributeCollection attributes;
+    xUnitpp::TestCollection collection;
+    xUnitpp::TestCollection::Register reg(collection, test, "LineInfoOverridesDefaultTestLineInfo", "LineInfo", attributes, -1, __FILE__, __LINE__);
+
+
+}
+
+}

Tests/Tests.vcxproj

     <ClCompile Include="Assert.Throws.cpp" />
     <ClCompile Include="Assert.True.cpp" />
     <ClCompile Include="Attributes.cpp" />
+    <ClCompile Include="LineInfo.cpp" />
     <ClCompile Include="Theory.cpp" />
   </ItemGroup>
   <ItemGroup>

Tests/Tests.vcxproj.filters

     <ClCompile Include="Assert.True.cpp" />
     <ClCompile Include="Attributes.cpp" />
     <ClCompile Include="Theory.cpp" />
+    <ClCompile Include="LineInfo.cpp" />
   </ItemGroup>
 </Project>
         {
         }
 
-        virtual void ReportFailure(const xUnitpp::TestDetails &, int, const std::string &) override
+        virtual void ReportFailure(const xUnitpp::TestDetails &, int, const std::string &, const xUnitpp::LineInfo &) override
         {
         }
 
 Visual Studio 2012 notes
 ------------------------
 implement ITestDiscoverer and ITestExecutor
+create vsix for test runners
+need msbuild test runner
 
 
 General
 Stretch
 -----
 custom xUnitAsserts per assert (revisit unit tests at that point)
-consider doing LINEINFO the way VS2012 does
-support wstring - what does that mean?
-    - as an assert call paarameter?
-    - define std::tstring and add yet another set of compile targets?
-create NuGet package/template (NuGet does not support C++ projects, yet)
+support wstring as an assert call parameter
+create NuGet package/template (NuGet does not support C++ projects, yet)

xUnit++.console/StdOutReporter.cpp

 #include <chrono>
 #include <cstdio>
 #include <iostream>
+#include "LineInfo.h"
 #include "TestDetails.h"
 
 namespace
 {
-    std::string FileAndLine(const std::string &file, int line)
+    std::string FileAndLine(const xUnitpp::TestDetails &td, const xUnitpp::LineInfo lineInfo)
     {
+        auto file = lineInfo.file.empty() ? td.Filename : lineInfo.file;
+        auto line = lineInfo.file.empty() ? td.Line : lineInfo.line;
+
         return file + "(" + std::to_string(line) + ")";
     }
 
     }
 }
 
-void StdOutReporter::ReportFailure(const TestDetails &testDetails, int dataIndex, const std::string &msg)
+void StdOutReporter::ReportFailure(const TestDetails &testDetails, int dataIndex, const std::string &msg, const LineInfo &lineInfo)
 {
-    std::cout << (FileAndLine(testDetails.Filename, testDetails.Line) +
+    std::cout << (FileAndLine(testDetails, lineInfo) +
         ": error in " + NameAndDataIndex(testDetails.Name, dataIndex) + ": " + msg + "\n");
 }
 
 void StdOutReporter::ReportSkip(const TestDetails &testDetails, const std::string &reason)
 {
-    std::cout << (FileAndLine(testDetails.Filename, testDetails.Line) +
+    std::cout << (FileAndLine(testDetails, LineInfo::empty()) +
         ": skipping " + testDetails.Name + ": " + reason + "\n");
 }
 

xUnit++.console/StdOutReporter.h

     StdOutReporter(bool verbose, bool veryVerbose);
 
     virtual void ReportStart(const TestDetails &, int) override;
-    virtual void ReportFailure(const TestDetails &testDetails, int dataIndex, const std::string &msg) override;
+    virtual void ReportFailure(const TestDetails &testDetails, int dataIndex, const std::string &msg, const LineInfo &lineInfo) override;
     virtual void ReportSkip(const TestDetails &testDetails, const std::string &reason) override;
     virtual void ReportFinish(const TestDetails &, int, xUnitpp::Duration) override;
     virtual void ReportAllTestsComplete(size_t testCount, size_t skipped, size_t failureCount, xUnitpp::Duration totalTime) override;

xUnit++.console/XmlReporter.cpp

     suiteResults[testDetails.Suite].testResults.insert(std::make_pair(TestName(testDetails.Name, dataIndex), TestResult(testDetails)));
 }
 
-void XmlReporter::ReportFailure(const TestDetails &testDetails, int dataIndex, const std::string &msg)
+void XmlReporter::ReportFailure(const TestDetails &testDetails, int dataIndex, const std::string &msg, const LineInfo &)
 {
     std::string testName = TestName(testDetails.Name, dataIndex);
     suiteResults[testDetails.Suite].failures++;

xUnit++.console/XmlReporter.h

     XmlReporter(const std::string &filename);
 
     virtual void ReportStart(const TestDetails &td, int dataIndex) override;
-    virtual void ReportFailure(const TestDetails &testDetails, int dataIndex, const std::string &msg) override;
+    virtual void ReportFailure(const TestDetails &testDetails, int dataIndex, const std::string &msg, const LineInfo &lineInfo) override;
     virtual void ReportSkip(const TestDetails &testDetails, const std::string &reason) override;
     virtual void ReportFinish(const TestDetails &testDetails, int dataIndex, xUnitpp::Duration timeTaken) override;
     virtual void ReportAllTestsComplete(size_t testCount, size_t skipped, size_t failureCount, xUnitpp::Duration totalTime) override;

xUnit++/IOutput.h

 namespace xUnitpp
 {
 
+struct LineInfo;
 struct TestDetails;
 
 struct IOutput
     virtual ~IOutput();
 
     virtual void ReportStart(const TestDetails &testDetails, int dataIndex) = 0;
-    virtual void ReportFailure(const TestDetails &testDetails, int dataIndex, const std::string &msg) = 0;
+    virtual void ReportFailure(const TestDetails &testDetails, int dataIndex, const std::string &msg, const LineInfo &lineInfo) = 0;
     virtual void ReportSkip(const TestDetails &testDetails, const std::string &reason) = 0;
     virtual void ReportFinish(const TestDetails &testDetails, int dataIndex, xUnitpp::Duration timeTaken) = 0;
     virtual void ReportAllTestsComplete(size_t testCount, size_t skipped, size_t failed, xUnitpp::Duration totalTime) = 0; 

xUnit++/LineInfo.cpp

+#include "LineInfo.h"
+
+namespace xUnitpp
+{
+
+LineInfo::LineInfo()
+{
+}
+
+LineInfo::LineInfo(const std::string &file, int line)
+    : file(file)
+    , line(line)
+{
+}
+
+const LineInfo &LineInfo::empty()
+{
+    static LineInfo empty;
+    return empty;
+}
+
+}

xUnit++/LineInfo.h

+#ifndef LINEINFO_H_
+#define LINEINFO_H_
+
+#include <string>
+
+namespace xUnitpp
+{
+
+struct LineInfo
+{
+    LineInfo(const std::string &file, int line);
+
+    static const LineInfo &empty();
+
+    std::string file;
+    int line;
+
+private:
+    LineInfo();
+};
+
+}
+
+#endif

xUnit++/TestCollection.h

 #include <functional>
 #include <map>
 #include <vector>
+#include "Fact.h"
 #include "Theory.h"
 
 namespace xUnitpp
 {
 
-class Fact;
-
 class TestCollection
 {
     friend class Register;

xUnit++/xUnit++.vcxproj

   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Fact.cpp" />
+    <ClCompile Include="LineInfo.cpp" />
     <ClCompile Include="TestCollection.cpp" />
     <ClCompile Include="TestDetails.cpp" />
     <ClCompile Include="Theory.cpp" />
     <ClInclude Include="Fact.h" />
     <ClInclude Include="ForceLinkModuleMacros.h" />
     <ClInclude Include="IOutput.h" />
+    <ClInclude Include="LineInfo.h" />
     <ClInclude Include="Suite.h" />
     <ClInclude Include="TestCollection.h" />
     <ClInclude Include=".\xUnitMacros.h" />

xUnit++/xUnit++.vcxproj.filters

     <ClCompile Include="Theory.cpp" />
     <ClCompile Include="TestDetails.cpp" />
     <ClCompile Include="xUnitTestRunner.cpp" />
+    <ClCompile Include="LineInfo.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Fact.h" />
     <ClInclude Include="IOutput.h" />
     <ClInclude Include="ForceLinkModuleMacros.h" />
     <ClInclude Include="ExportApi.h" />
+    <ClInclude Include="LineInfo.h" />
   </ItemGroup>
 </Project>

xUnit++/xUnitAssert.cpp

 {
 
 xUnitAssert::xUnitAssert(const std::string &call, const std::string &userMsg, const std::string &customMsg,
-                         const std::string &expected, const std::string &actual)
+                         const std::string &expected, const std::string &actual, const xUnitpp::LineInfo &lineInfo)
     : base(AssembleWhat(call, userMsg, customMsg, expected, actual).c_str())
+    , lineInfo(lineInfo)
 {
 }
 
+xUnitAssert::xUnitAssert(const xUnitAssert &other)
+    : base(other.what())
+    , lineInfo(other.lineInfo)
+{
+}
+
+const LineInfo &xUnitAssert::LineInfo() const
+{
+    return lineInfo;
+}
+
 double Assert::round(double value, size_t precision)
 {
     if (value < 0)
     }
 }
 
-void Assert::Equal(float expected, float actual, int precision, const std::string &msg) const
+void Assert::Equal(const std::string &expected, const std::string &actual, const std::string &msg, const LineInfo &lineInfo) const
 {
-    Equal((double)expected, (double)actual, precision, msg);
+    if (expected != actual)
+    {
+        throw xUnitAssert("Equal", msg, "", expected, actual, lineInfo);
+    }
 }
 
-void Assert::Equal(double expected, double actual, int precision, const std::string &msg) const
+void Assert::Equal(const std::string &expected, const std::string &actual, const LineInfo &lineInfo) const
+{
+    Equal(expected, actual, std::string(""), lineInfo);
+}
+
+void Assert::Equal(const char *expected, const char *actual, const std::string &msg, const LineInfo &lineInfo) const
+{
+    Equal(std::string(expected), std::string(actual), msg, lineInfo);
+}
+
+void Assert::Equal(const char *expected, const char *actual, const LineInfo &lineInfo) const
+{
+    Equal(std::string(expected), std::string(actual), std::string(""), 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
 {
     auto er = round(expected, precision);
     auto ar = round(actual, precision);
 
-    Equal(er, ar, [](double er, double ar) { return er == ar; }, msg);
+    Equal(er, ar, [](double er, double ar) { return er == ar; }, msg, lineInfo);
 }
 
-void Assert::Fail(const std::string &msg) const
+void Assert::Equal(double expected, double actual, int precision, const LineInfo &lineInfo) const
 {
-    throw xUnitAssert("Fail", msg, "", "", "");
+    Equal(expected, actual, precision, "", lineInfo);
 }
 
-void Assert::False(bool b, const std::string &msg) const
+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
 {
     if (b)
     {
-        throw xUnitAssert("False", msg, "", "false", "true");
+        throw xUnitAssert("False", msg, "", "false", "true", lineInfo);
     }
 }
 
-void Assert::True(bool b, const std::string &msg) const
+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
 {
     if (!b)
     {
-        throw xUnitAssert("True", msg, "", "true", "false");
+        throw xUnitAssert("True", msg, "", "true", "false", lineInfo);
     }
 }
 
-void Assert::DoesNotContain(const char *actualString, const char *value, const std::string &msg) const
+void Assert::True(bool b, const LineInfo &lineInfo) const
 {
-    DoesNotContain(std::string(actualString), std::string(value), msg);
+    True(b, "", lineInfo);
 }
 
-void Assert::DoesNotContain(const std::string &actualString, const char *value, const std::string &msg) const
+void Assert::DoesNotContain(const char *actualString, const char *value, const std::string &msg, const LineInfo &lineInfo) const
 {
-    DoesNotContain(actualString, std::string(value), msg);
+    DoesNotContain(std::string(actualString), std::string(value), msg, lineInfo);
 }
 
-void Assert::DoesNotContain(const std::string &actualString, const std::string &value, const std::string &msg) const
+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
 {
     auto found = actualString.find(value);
     if (found != std::string::npos)
     {
-        throw xUnitAssert("DoesNotContain", msg, "Found: \"" + value + "\" at position " + std::to_string(found) + ".", "", "");
+        throw xUnitAssert("DoesNotContain", msg, "Found: \"" + value + "\" at position " + std::to_string(found) + ".", "", "", lineInfo);
     }
 }
 
-void Assert::Contains(const char *actualString, const char *value, const std::string &msg) const
+void Assert::DoesNotContain(const std::string &actualString, const std::string &value, const LineInfo &lineInfo) const
 {
-    Contains(std::string(actualString), std::string(value), msg);
+    DoesNotContain(actualString, value, "", lineInfo);
 }
 
-void Assert::Contains(const std::string &actualString, const char *value, const std::string &msg) const
+void Assert::Contains(const char *actualString, const char *value, const std::string &msg, const LineInfo &lineInfo) const
 {
-    Contains(actualString, std::string(value), msg);
+    Contains(std::string(actualString), std::string(value), msg, lineInfo);
 }
 
-void Assert::Contains(const std::string &actualString, const std::string &value, const std::string &msg) const
+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
 {
     if (actualString.find(value) == std::string::npos)
     {
-        throw xUnitAssert("Contains", msg, "", actualString, value);
+        throw xUnitAssert("Contains", msg, "", actualString, value, lineInfo);
     }
 }
 
+void Assert::Contains(const std::string &actualString, const std::string &value, const LineInfo &lineInfo) const
+{
+    Contains(actualString, value, "", lineInfo);
 }
+
+}

xUnit++/xUnitAssert.h

 #include <exception>
 #include <string>
 #include <type_traits>
+#include "LineInfo.h"
 
 namespace xUnitpp
 {
 
 public:
     xUnitAssert(const std::string &call, const std::string &userMsg, const std::string &customMsg,
-                const std::string &expected, const std::string &actual);
+                const std::string &expected, const std::string &actual, const LineInfo &lineInfo);
+    xUnitAssert(const xUnitAssert &other);
+
+    const LineInfo &LineInfo() const;
+
+private:
+    xUnitpp::LineInfo lineInfo;
 };
 
 const class Assert
 private:
     static double round(double value, size_t precision);
 
-    template<typename T0>
-    static std::string RangeToString(const T0 &begin, const T0 &end)
+    template<typename T>
+    static std::string RangeToString(const T &begin, const T &end)
     {
         std::string result = "[ ";
 
     };
 
 public:
-    template<typename T0, typename T1, typename TComparer>
-    void Equal(T0 t0, T1 t1, TComparer comparer, const std::string &msg = "") const
+    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
     {
         using namespace std;
 
-        if (!comparer(t0, t1))
+        if (!comparer(expected, actual))
         {
-            throw xUnitAssert("Equal", msg, "", to_string(t0), to_string(t1));
+            throw xUnitAssert("Equal", msg, "", to_string(expected), to_string(actual), lineInfo);
         }
     }
 
-    template<typename T0, typename T1>
-    void Equal(T0 t0, T1 t1, const std::string &msg = "") const
+    template<typename TExpected, typename TActual, typename TComparer>
+    void Equal(TExpected expected, TActual actual, TComparer comparer, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        Equal(t0, t1, [](T0 t0, T1 t1) { return t0 == t1; }, msg);
+        Equal(expected, actual, comparer, "", lineInfo);
     }
 
-    void Equal(float expected, float actual, int precision, const std::string &msg = "") const;
-    void Equal(double expected, double actual, int precision, const std::string &msg = "") const;
+    template<typename TExpected, typename TActual>
+    void Equal(TExpected expected, TActual actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        Equal(expected, actual, [](TExpected expected, TActual actual) { return expected == actual; }, msg, lineInfo);
+    }
 
-    template<typename TSeq0, typename TSeq1, typename TComparer>
-    void Equal(const TSeq0 &begin0, const TSeq0 &end0, const TSeq1 &begin1, const TSeq1 &end1, TComparer comparer, const std::string &msg = "") const
+    template<typename TExpected, typename TActual>
+    void Equal(TExpected expected, TActual actual, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        auto cur0 = begin0;
-        auto cur1 = begin1;
+        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;
+
+    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
+    {
+        auto expected = expectedBegin;
+        auto actual = actualBegin;
 
         size_t index = 0;
-        while (cur0 != end0 && cur1 != end1)
+        while (expected != expectedEnd && actual != actualEnd)
         {
-            if (!comparer(*cur0, *cur1))
+            if (!comparer(*expected, *actual))
             {
                 break;
             }
 
-            ++cur0;
-            ++cur1;
+            ++expected;
+            ++actual;
             ++index;
         }
 
-        if (cur0 != end0 || cur1 != end1)
+        if (expected != expectedEnd || actual != actualEnd)
         {
             throw xUnitAssert("Equal", msg,
                 "Sequence unequal at location " + std::to_string(index) + ".",
-                RangeToString(begin0, end0),
-                RangeToString(begin1, end1));
+                RangeToString(expectedBegin, expectedEnd),
+                RangeToString(actualBegin, actualEnd),
+                lineInfo);
         }
     }
 
-    template<typename TSeq0, typename TSeq1>
-    void Equal(const TSeq0 &begin0, const TSeq0 &end0, const TSeq1 &begin1, const TSeq1 &end1, const std::string &msg = "") 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 LineInfo &lineInfo = LineInfo::empty()) const
     {
-        Equal(begin0, end0, begin1, end1, [](decltype(*begin0) a, decltype(*begin1) b) { return a == b; }, msg);
+        Equal(expectedBegin, expectedEnd, actualBegin, actualEnd, comparer, "", lineInfo);
     }
 
-    template<typename T0, typename T1, typename TComparer>
-    void NotEqual(T0 t0, T1 t1, TComparer comparer, const std::string &msg = "") const
+    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
     {
-        if (comparer(t0, t1))
+        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);
+    }
+
+    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, "", "", "");
+            throw xUnitAssert("NotEqual", msg, "", "", "", lineInfo);
         }
     }
 
-    template<typename T0, typename T1>
-    void NotEqual(T0 t0, T1 t1, const std::string &msg = "") const
+    template<typename TExpected, typename TActual, typename TComparer>
+    void NotEqual(TExpected expected, TActual actual, TComparer comparer, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        NotEqual(t0, t1, [](T0 t0, T1 t1) { return t0 == t1; }, msg);
+        NotEqual(expected, actual, comparer, "", lineInfo);
     }
 
-    template<typename TSeq0, typename TSeq1, typename TComparer>
-    void NotEqual(const TSeq0 &begin0, const TSeq0 &end0, const TSeq1 &begin1, const TSeq1 &end1, TComparer comparer, const std::string &msg = "") const
+    template<typename TExpected, typename TActual>
+    void NotEqual(TExpected expected, TActual actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        auto cur0 = begin0;
-        auto cur1 = begin1;
+        NotEqual(expected, actual, [](TExpected expected, TActual actual) { return expected == actual; }, msg, lineInfo);
+    }
 
-        while (cur0 != end0 && cur1 != end1)
+    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
+    {
+        auto expected = expectedBegin;
+        auto actual = actualBegin;
+
+        while (expected != expectedEnd && actual != actualEnd)
         {
-            if (!comparer(*cur0, *cur1))
+            if (!comparer(*expected, *actual))
             {
                 return;
             }
 
-            ++cur0;
-            ++cur1;
+            ++expected;
+            ++actual;
         }
 
-        if (cur0 == end0 && cur1 == end1)
+        if (expected == expectedEnd && actual == actualEnd)
         {
-            throw xUnitAssert("NotEqual", msg, "", "", "");
+            throw xUnitAssert("NotEqual", msg, "", "", "", lineInfo);
         }
     }
 
-    template<typename TSeq0, typename TSeq1>
-    void NotEqual(const TSeq0 &begin0, const TSeq0 &end0, const TSeq1 &begin1, const TSeq1 &end1, const std::string &msg = "") const
+    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(begin0, end0, begin1, end1, [](decltype(*begin0) a, decltype(*begin1) b) { return a == b; }, msg);
+        NotEqual(expectedBegin, expectedEnd, actualBegin, actualEnd, comparer, "", lineInfo);
+    }
+
+    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
+    {
+        NotEqual(expectedBegin, expectedEnd, actualBegin, actualEnd, [](decltype(*expectedBegin) a, decltype(*actualBegin) b) { return a == b; }, msg, 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
+    void DoesNotThrow(TFunc &&fn, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
     {
         try
         {
             fn();
         }
-        catch (std::exception &e)
+        catch (const std::exception &e)
         {
-            throw xUnitAssert("DoesNotThrow", msg, "", "(no exception)", e.what());
+            throw xUnitAssert("DoesNotThrow", msg, "", "(no exception)", e.what(), lineInfo);
         }
         catch (...)
         {
-            throw xUnitAssert("DoesNotThrow", msg, "", "(no exception)", "Crash: unknown exception.");
+            throw xUnitAssert("DoesNotThrow", msg, "", "(no exception)", "Crash: unknown exception.", lineInfo);
         }
     }
 
+    template<typename TFunc>
+    void DoesNotThrow(TFunc &&fn, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        DoesNotThrow(fn, "", lineInfo);
+    }
+
     template<typename TException, typename TFunc>
-    TException Throws(TFunc &&fn, const std::string &msg = "") const
+    TException Throws(TFunc &&fn, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
     {
         try
         {
             fn();
         }
-        catch (TException e)
+        catch (const TException &e)
         {
             return e;
         }
         catch (const std::exception &e)
         {
-            throw xUnitAssert("Throws", msg, "", typeid(TException).name(), e.what());
+            throw xUnitAssert("Throws", msg, "", typeid(TException).name(), e.what(), lineInfo);
         }
         catch (...)
         {
-            throw xUnitAssert("Throws", msg, "", typeid(TException).name(), "Crash: unknown exception.");
+            throw xUnitAssert("Throws", msg, "", typeid(TException).name(), "Crash: unknown exception.", lineInfo);
         }
 
-        throw xUnitAssert("Throws", msg, "", typeid(TException).name(), "No exception.");
+        throw xUnitAssert("Throws", msg, "", typeid(TException).name(), "No exception.", lineInfo);
     }
 
-    void Fail(const std::string &msg = "") const;
+    template<typename TException, typename TFunc>
+    TException Throws(TFunc &&fn, const LineInfo &lineInfo = LineInfo::empty()) const
+    {
+        return Throws<TException>(fn, "", lineInfo);
+    }
 
-    void False(bool b, const std::string &msg = "") const;
+    void Fail(const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const;
+    void Fail(const LineInfo &lineInfo = LineInfo::empty()) const;
 
-    void True(bool b, const std::string &msg = "") 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
+    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, "", "", "");
+            throw xUnitAssert("Empty", msg, "", "", "", lineInfo);
         }
     }
 
     template<typename TSequence>
-    typename std::enable_if<!has_empty<TSequence>::value>::type Empty(const TSequence &sequence, const std::string &msg = "") const
+    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, "", "", "");
+            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
+    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)) + ".", "", "");
+            throw xUnitAssert("DoesNotContain", msg, "Found: matching value at position " + to_string(distance(begin(sequence), found)) + ".", "", "", lineInfo);
         }
     }
 
-    template<typename TSequence, typename T>
-    void DoesNotContain(const TSequence &sequence, T value, const std::string &msg = "") const
+    template<typename TSequence, typename TPredicate>
+    void DoesNotContainPred(const TSequence &sequence, TPredicate &&predicate, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        DoesNotContainPred(sequence, [&value](const T& actual) { return actual == value; }, msg);
+        DoesNotContainPred(sequence, predicate, "", lineInfo);
     }
 
-    void DoesNotContain(const char *actualString, const char *value, const std::string &msg = "") const;
+    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);
+    }
 
-    void DoesNotContain(const std::string &actualString, const char *value, const std::string &msg = "") const;
+    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 std::string &actualString, const std::string &value, const std::string &msg = "") const;
+    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
+    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, "", "", "");
+            throw xUnitAssert("Contains", msg, "", "", "", lineInfo);
         }
     }
 
-    template<typename TSequence, typename T>
-    void Contains(const TSequence &sequence, T value, const std::string &msg = "") const
+    template<typename TSequence, typename TPredicate>
+    void ContainsPred(const TSequence &sequence, TPredicate &&predicate, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        ContainsPred(sequence, [&value](const T &actual) { return actual == value; }, msg); 
+        ContainsPred(sequence, predicate, "", lineInfo);
     }
 
-    void Contains(const char *actualString, const char *value, const std::string &msg = "") const;
+    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); 
+    }
 
-    void Contains(const std::string &actualString, const char *value, const std::string &msg = "") const;
+    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 std::string &actualString, const std::string &value, const std::string &msg = "") const;
+    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
+    void InRange(TActual actual, TRange min, TRange max, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
     {
         if (min >= max)
         {
 
         if (actual < min || actual >= max)
         {
-            throw xUnitAssert("InRange", msg, "", "[" + std::to_string(min) + " - " + std::to_string(max) + ")", std::to_string(actual));
+            throw xUnitAssert("InRange", 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 std::string &msg = "") const
+    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)
         {
 
         if (actual >= min && actual < max)
         {
-            throw xUnitAssert("NotInRange", msg, "", "[" + std::to_string(min) + " - " + std::to_string(max) + ")", std::to_string(actual));
+            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 std::string &msg = "") const
+    void NotNull(const T &value, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        if (value == nullptr)
+        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("NotNull", msg, "", "", "");
+            throw xUnitAssert("Null", msg, "", "", "", lineInfo);
         }
     }
 
     template<typename T>
-    void Null(const T &value, const std::string &msg = "") const
+    void Null(const T &value, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        if (value != nullptr)
+        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("Null", msg, "", "", "");
+            throw xUnitAssert("NotSame", msg, "", "", "", lineInfo);
         }
     }
 
     template<typename T>
-    void NotSame(const T &t0, const T &t1, const std::string &msg = "") const
+    void NotSame(const T &expected, const T &actual, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        if (&t0 == &t1)
+        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, "", "", "");
+            throw xUnitAssert("NotSame", msg, "", "", "", lineInfo);
         }
     }
 
     template<typename T>
-    void NotSame(const T *t0, const T *t1, const std::string &msg = "") const
+    void NotSame(T *expected, T *actual, const std::string &msg, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        if (t0 == t1)
+        if (expected == actual)
         {
-            throw xUnitAssert("NotSame", msg, "", "", "");
+            throw xUnitAssert("NotSame", msg, "", "", "", lineInfo);
         }
     }
 
     template<typename T>
-    void Same(const T &t0, const T &t1, const std::string &msg = "") const
+    void NotSame(T *expected, T *actual, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        if (&t0 != &t1)
+        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, "", "", "");
+            throw xUnitAssert("Same", msg, "", "", "", lineInfo);
         }
     }
 
     template<typename T>
-    void Same(T *t0, T *t1, const std::string &msg = "") const
+    void Same(const T &expected, const T &actual, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        if (t0 != t1)
+        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, "", "", "");
+            throw xUnitAssert("Same", msg, "", "", "", lineInfo);
         }
     }
 
     template<typename T>
-    void Same(const T *t0, const T *t1, const std::string &msg = "") const
+    void Same(T *expected, T *actual, const LineInfo &lineInfo = LineInfo::empty()) const
     {
-        if (t0 != t1)
+        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, "", "", "");
+            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;
 
 }

xUnit++/xUnitMacros.h

 #include <tuple>
 #include <vector>
 #include "Attributes.h"
+#include "LineInfo.h"
 #include "TestCollection.h"
 #include "TestDetails.h"
 #include "Suite.h"
 #define THEORY_PROVIDER_END \
     }
 
+#define LI xUnitpp::LineInfo(__FILE__, __LINE__)
+
 #endif

xUnit++/xUnitTestRunner.cpp

         mTestReporter.ReportStart(details, dataIndex);
     }
 
-    void OnTestFailure(const TestDetails &details, int dataIndex, const std::string &message)
+    void OnTestFailure(const TestDetails &details, int dataIndex, const std::string &message, const LineInfo &lineInfo)
     {
         std::lock_guard<std::mutex> guard(mFailureMtx);
-        mTestReporter.ReportFailure(details, dataIndex, message);
+        mTestReporter.ReportFailure(details, dataIndex, message, lineInfo);
     }
 
     void OnTestSkip(const TestDetails &details, const std::string &reason)
                             testStart = Clock::now();
                             test.test();
                         }
-                        catch (std::exception &e)
+                        catch (const xUnitAssert &e)
                         {
-                            mImpl->OnTestFailure(test.testDetails, test.dataIndex, e.what());
+                            mImpl->OnTestFailure(test.testDetails, test.dataIndex, e.what(), e.LineInfo());
+                        }
+                        catch (const std::exception &e)
+                        {
+                            mImpl->OnTestFailure(test.testDetails, test.dataIndex, e.what(), LineInfo::empty());
                             ++failedTests;
                         }
                         catch (...)
                         {
-                            mImpl->OnTestFailure(test.testDetails, test.dataIndex, "Unknown exception caught: test has crashed");
+                            mImpl->OnTestFailure(test.testDetails, test.dataIndex, "Unknown exception caught: test has crashed", LineInfo::empty());
                             ++failedTests;
                         }
 
 
                     if (threadStarted->wait_for(gate, std::chrono::duration_cast<std::chrono::nanoseconds>(testTimeLimit)) == std::cv_status::timeout)
                     {
-                        mImpl->OnTestFailure(test.testDetails, test.dataIndex, "Test failed to complete within " + std::to_string(ToMilliseconds(testTimeLimit).count()) + " milliseconds.");
+                        mImpl->OnTestFailure(test.testDetails, test.dataIndex, "Test failed to complete within " + std::to_string(ToMilliseconds(testTimeLimit).count()) + " milliseconds.", LineInfo::empty());
                         mImpl->OnTestFinish(test.testDetails, test.dataIndex, testTimeLimit);
                         ++failedTests;
                     }