How To Use
 All Modules Pages
C++ Example: checking an arbitrary subtree within XML data (XmlCheck::CheckNode)
#include "stdafx.h"
#include "MyTestCommands.h"
#include <pugixml.hpp>
#include <TestToolBox\TestToolBox.h>
#include <boost/test/unit_test.hpp>
namespace TTB = TestToolBox;
//-----------------------------------------------------------------------------
class MyTestSuiteFixture
{
public:
MyTestSuiteFixture()
{
TTB_INFO("\nMyTestSuiteFixture-Constructor");
}
~MyTestSuiteFixture()
{
TTB_INFO("\nMyTestSuiteFixture-Destructor");
// Reset XmlCheck to default
TTB::TheXmlCheck()->SetDefaults();
}
};
class MyTestCaseFixture
{
public:
MyTestCaseFixture()
{
TTB_INFO("\nMyTestCaseFixture-Constructor");
}
~MyTestCaseFixture()
{
TTB_INFO("\nMyTestCaseFixture-Destructor");
}
};
TTB_BOOST_TEST_CASE(TestCaseZ)
{
std::cout << "this is <defaultSuite>/TestCaseZ" << std::endl;
}}
BOOST_AUTO_TEST_SUITE(Suite_RawBoostTestCaseWithFixture);
BOOST_FIXTURE_TEST_CASE(RawBoostTestCaseWithFixture, MyTestCaseFixture)
{
BOOST_CHECK(true);
}
TTB_BOOST_FIXTURE_TEST_CASE(TestCaseWithFixture, MyTestCaseFixture)
{
BOOST_CHECK(true);
}}
BOOST_AUTO_TEST_SUITE_END();
BOOST_FIXTURE_TEST_SUITE(SuiteCheckingNodes, MyTestSuiteFixture)
BOOST_AUTO_TEST_SUITE(NestedSuite);
BOOST_AUTO_TEST_SUITE(EmptyHierarchy);
BOOST_AUTO_TEST_SUITE(NestedSuite);
TTB_BOOST_TEST_CASE(TestCaseZ)
{
std::cout << "this is SuiteCheckingNodes/NestedSuite/NestedSuite/TestCaseZ" << std::endl;
}}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()
TTB_BOOST_TEST_CASE(InsideNestedTestSuite)
{
std::cout << "this is SuiteCheckingNodes/NestedSuite/InsideNestedTestSuite" << std::endl;
}}
TTB_BOOST_TEST_CASE(TestCaseZ)
{
std::cout << "this is SuiteCheckingNodes/NestedSuite/TestCaseZ" << std::endl;
}}
BOOST_AUTO_TEST_SUITE_END()
TTB_BOOST_TEST_CASE(TestCaseZ)
{
std::cout << "this is SuiteCheckingNodes/TestCaseZ" << std::endl;
}}
//-----------------------------------------------------------------------------
// Represents test case visible for both Boost and TestToolBox
TTB_BOOST_TEST_CASE(CheckSubNodesOfXmlTree)
{
//-------------------------------------------------------------------------
TTB_SECTION("Select a subnode using PugiXml child function or xpath functions and check with XmlCheck");
//-------------------------------------------------------------------------
TTB_INFO("\nCheck child Group_C");
pugi::xml_document doc;
pugi::xml_node root = TTB::TheXmlCheck()->ReadFromFile(doc, MY_XML_FILE_PATH);
pugi::xml_node nodeC = root.child("Group_C");
TTB::TheXmlCheck()->CheckNode(nodeC);
TTB_EXP("Group_C");
TTB_EXP(" Interior");
TTB_EXP(" Something");
TTB_EXP(" Some text");
TTB_EXP(" date");
TTB_EXP(" 28.09.09");
TTB_INFO("\nCheck child Group_C/Interior");
pugi::xml_node nodeCInterior = root.child("Group_C").child("Interior");
TTB::TheXmlCheck()->CheckNode(nodeCInterior);
TTB_EXP("Interior");
TTB_EXP(" Something");
TTB_EXP(" Some text");
TTB_EXP(" date");
TTB_EXP(" 28.09.09");
TTB_INFO("\nCheck child Group_C/Interior with pugixml xpath function");
pugi::xpath_node xpathNode = root.select_single_node("Group_C/Interior");
if (xpathNode)
{
pugi::xml_node selectedNode = xpathNode.node();
TTB::TheXmlCheck()->CheckNode(selectedNode);
TTB_EXP("Interior");
TTB_EXP(" Something");
TTB_EXP(" Some text");
TTB_EXP(" date");
TTB_EXP(" 28.09.09");
}
//-------------------------------------------------------------------------
TTB_SECTION("Directly check a subnode using XmlCheck");
//-------------------------------------------------------------------------
TTB::TheXmlCheck()->CheckSubNode(doc, "Group_C/Interior");
TTB_EXP("Interior");
TTB_EXP(" Something");
TTB_EXP(" Some text");
TTB_EXP(" date");
TTB_EXP(" 28.09.09");
TTB_INFO("\nCompact syntax");
pugi::xml_document tmpDoc;
TTB::TheXmlCheck()->CheckSubNode(TTB::TheXmlCheck()->ReadFromFile(tmpDoc, MY_XML_FILE_PATH), "Group_C/Interior");
TTB_EXP("Interior");
TTB_EXP(" Something");
TTB_EXP(" Some text");
TTB_EXP(" date");
TTB_EXP(" 28.09.09");
}}
//-----------------------------------------------------------------------------
TTB_BOOST_TEST_CASE(RestrictNumberOfReportedChilds)
{
pugi::xml_document doc;
TTB::TheXmlCheck()->ReadFromFile(doc, MY_XML_FILE_PATH);
TTB_INFO("\nCheck Group_A with only first child");
TTB::TheXmlCheck()->CheckSubNodeWithMaxChilds(1, doc, "Group_A");
TTB_EXP("Group_A");
TTB_EXP(" Vector");
TTB_EXP(" id: 1");
TTB_EXP(" date: 01.07.09");
TTB_EXP(" time: 09:15:12.234");
TTB_EXP(" tolerance: 0.0258");
TTB_EXP(" This is the text of the first vector element");
TTB_EXP(" x");
TTB_EXP(" 3.14235");
TTB_INFO("\nCheck Group_A with first two childs");
TTB::TheXmlCheck()->CheckSubNodeWithMaxChilds(2, doc, "Group_A");
TTB_EXP("Group_A");
TTB_EXP(" Vector");
TTB_EXP(" id: 1");
TTB_EXP(" date: 01.07.09");
TTB_EXP(" time: 09:15:12.234");
TTB_EXP(" tolerance: 0.0258");
TTB_EXP(" This is the text of the first vector element");
TTB_EXP(" x");
TTB_EXP(" 3.14235");
TTB_EXP(" Vector");
TTB_EXP(" id: 2");
TTB_EXP(" date: 01.07.09");
TTB_EXP(" time: 09:15:12.234");
TTB_EXP(" tolerance: 0.0375451");
TTB_EXP(" This is the text of the second vector element");
TTB_EXP(" x");
TTB_EXP(" 3.14235");
}}
//-----------------------------------------------------------------------------
TTB_BOOST_TEST_CASE(IgnoreAttributesAndNodes)
{
pugi::xml_document doc;
TTB::TheXmlCheck()->ReadFromFile(doc, MY_XML_FILE_PATH);
TTB::TheXmlCheck()->IgnoreAttribute("date");
TTB::TheXmlCheck()->IgnoreAttribute("time");
TTB::TheXmlCheck()->IgnoreNode("Group_B");
TTB::TheXmlCheck()->IgnoreNode("Something");
TTB::TheXmlCheck()->CheckNode(doc);
TTB_EXP("MyContainer");
TTB_EXP(" Group_A");
TTB_EXP(" Vector");
TTB_EXP(" id: 1");
TTB_EXP(" tolerance: 0.0258");
TTB_EXP(" This is the text of the first vector element");
TTB_EXP(" x");
TTB_EXP(" 3.14235");
TTB_EXP(" Vector");
TTB_EXP(" id: 2");
TTB_EXP(" tolerance: 0.0375451");
TTB_EXP(" This is the text of the second vector element");
TTB_EXP(" x");
TTB_EXP(" 3.14235");
TTB_EXP(" Vector");
TTB_EXP(" id: 3");
TTB_EXP(" tolerance: 1.357");
TTB_EXP(" x");
TTB_EXP(" 6.28532");
TTB_EXP(" Group_C");
TTB_EXP(" Interior");
TTB_EXP(" date");
TTB_EXP(" 28.09.09");
}}
//-----------------------------------------------------------------------------
TTB_BOOST_TEST_CASE(ChoosePrecisionWhenCheckingDoubleValues)
{
pugi::xml_document doc;
TTB::TheXmlCheck()->ReadFromFile(doc, MY_XML_FILE_PATH);
// First reduce output
TTB::TheXmlCheck()->IgnoreAttribute("date");
TTB::TheXmlCheck()->IgnoreAttribute("time");
TTB::TheXmlCheck()->IgnoreNode("Group_B");
TTB::TheXmlCheck()->IgnoreNode("Group_C");
TTB_INFO("Check tolerance with precision 2 and x with precision 1");
TTB::TheXmlCheck()->UseAsDoubleAttribute("tolerance", true, 2);
TTB::TheXmlCheck()->UseAsDoubleNode("x", true, 1);
TTB::TheXmlCheck()->CheckNode(doc);
TTB_EXP("MyContainer");
TTB_EXP(" Group_A");
TTB_EXP(" Vector");
TTB_EXP(" id: 1");
TTB_EXP(" tolerance: 0.03");
TTB_EXP(" This is the text of the first vector element");
TTB_EXP(" x");
TTB_EXP(" 3.1");
TTB_EXP(" Vector");
TTB_EXP(" id: 2");
TTB_EXP(" tolerance: 0.04");
TTB_EXP(" This is the text of the second vector element");
TTB_EXP(" x");
TTB_EXP(" 3.1");
TTB_EXP(" Vector");
TTB_EXP(" id: 3");
TTB_EXP(" tolerance: 1.36");
TTB_EXP(" x");
TTB_EXP(" 6.3");
TTB_INFO("\nCheck tolerance with precision 3 and x with precision 2");
TTB::TheXmlCheck()->UseAsDoubleAttribute("tolerance", true, 3);
TTB::TheXmlCheck()->UseAsDoubleNode("x", true, 2);
TTB::TheXmlCheck()->CheckNode(doc);
TTB_EXP("MyContainer");
TTB_EXP(" Group_A");
TTB_EXP(" Vector");
TTB_EXP(" id: 1");
TTB_EXP(" tolerance: 0.026");
TTB_EXP(" This is the text of the first vector element");
TTB_EXP(" x");
TTB_EXP(" 3.14");
TTB_EXP(" Vector");
TTB_EXP(" id: 2");
TTB_EXP(" tolerance: 0.038");
TTB_EXP(" This is the text of the second vector element");
TTB_EXP(" x");
TTB_EXP(" 3.14");
TTB_EXP(" Vector");
TTB_EXP(" id: 3");
TTB_EXP(" tolerance: 1.357");
TTB_EXP(" x");
TTB_EXP(" 6.29");
}}
//-----------------------------------------------------------------------------
TTB_BOOST_TEST_CASE(ShortDemo_BasicUsage)
{
/// [xmlcheck basic usage read from string]
static const std::string SIMPLE_DEMO =
R"(<MyRootNode created="15.02.2015">
<SubNode id="17">contents of subnode</SubNode>
</MyRootNode>
)";
pugi::xml_document doc;
TTB::TheXmlCheck()->ReadFromString(doc, SIMPLE_DEMO);
/// [xmlcheck basic usage read from string]
/// [xmlcheck basic usage write to file]
static const std::string MY_XML_FILE_PATH_SIMPLE_DEMO = MY_TEST_DIR + "/SimpleDemo.xml";
TTB::TheXmlCheck()->SaveToFile(doc, MY_XML_FILE_PATH_SIMPLE_DEMO);
/// [xmlcheck basic usage write to file]
/// [xmlcheck basic usage read from file]
TTB::TheXmlCheck()->ReadFromFile(doc, MY_XML_FILE_PATH_SIMPLE_DEMO);
/// [xmlcheck basic usage read from file]
/// [xmlcheck basic usage check xml contents]
// Iterate over xml tree and generate a textual "TestEvent"
// for each logical entity:
TTB::TheXmlCheck()->CheckNode(doc);
// Verify each entity with a separate call to "TTB_EXP"
TTB_EXP("MyRootNode");
TTB_EXP(" created: 15.02.2015");
TTB_EXP(" SubNode");
TTB_EXP(" id: 17");
TTB_EXP(" contents of subnode");
/// [xmlcheck basic usage check xml contents]
}}
//-----------------------------------------------------------------------------
TTB_BOOST_TEST_CASE(ShortDemo_WriteXmlTreeToTestProtocolWithoutNeedForVerification)
{
pugi::xml_document doc;
TTB::TheXmlCheck()->ReadFromFile(doc, MY_XML_FILE_PATH);
/// [xmlcheck write to test protocol]
TTB_INFO("Regular output of xml tree - no need for exact verification");
TTB::TheXmlCheck()->SetOutputModeForWritingXmlContents(TTB::CTX_INFO);
TTB::TheXmlCheck()->CheckNode(doc); // no output
TTB_INFO("More detailed output of xml tree - no need for exact verification");
TTB::TheXmlCheck()->SetDetailedOutput(true);
TTB::TheXmlCheck()->CheckNode(doc); // no output
/// [xmlcheck write to test protocol]
}}
//-----------------------------------------------------------------------------
TTB_BOOST_TEST_CASE(ShortDemo_CheckDoubleWithDesiredPrecision)
{
/// [xmlcheck double values sample]
static const std::string SHORT_DEMO =
R"(<SomeNode attrA="1.23456789">
<SubNodeB>0.2468012345</SubNodeB>
</SomeNode>
)";
/// [xmlcheck double values sample]
/// [xmlcheck double values std check]
TTB_INFO("Check with standard settings");
pugi::xml_document doc;
TTB::TheXmlCheck()->ReadFromString(doc, SHORT_DEMO);
TTB::TheXmlCheck()->CheckNode(doc);
TTB_EXP("SomeNode");
TTB_EXP(" attrA: 1.23456789");
TTB_EXP(" SubNodeB");
TTB_EXP(" 0.2468012345");
/// [xmlcheck double values std check]
/// [xmlcheck double values small precision]
TTB_INFO("\nCheck with small precision");
TTB::TheXmlCheck()->UseAsDoubleAttribute("attrA", true, 3);
TTB::TheXmlCheck()->UseAsDoubleNode("SubNodeB", true, 2);
TTB::TheXmlCheck()->CheckNode(doc);
TTB_EXP("SomeNode");
TTB_EXP(" attrA: 1.235");
TTB_EXP(" SubNodeB");
TTB_EXP(" 0.25");
/// [xmlcheck double values small precision]
/// [xmlcheck double values increased precision]
TTB_INFO("\nCheck with increased precision");
TTB::TheXmlCheck()->UseAsDoubleAttribute("attrA", true, 5);
TTB::TheXmlCheck()->UseAsDoubleNode("SubNodeB", true, 5);
TTB::TheXmlCheck()->CheckNode(doc);
TTB_EXP("SomeNode");
TTB_EXP(" attrA: 1.23457");
TTB_EXP(" SubNodeB");
TTB_EXP(" 0.24680");
/// [xmlcheck double values increased precision]
}}
//-----------------------------------------------------------------------------
TTB_BOOST_TEST_CASE(ShortDemo_CheckSubNodeSelectedByXPath)
{
/// [xmlcheck select with xpath sample]
static const std::string SHORT_DEMO = R"(
<SomeNode>
<Child Id="1001">Contents of child 1</Child>
<Child Id="1002">Contents of child 2</Child>
<Child Id="1003">Contents of child 3</Child>
<Child Id="1004">Contents of child 4>
<SubChild color="red">Red contents</SubChild>
<SubChild color="blue">Blue contents</SubChild>
<SubChild color="green">Green contents</SubChild>
</Child>
<Child Id="1005">Contents of child 5</Child>
</SomeNode>
)";
/// [xmlcheck select with xpath sample]
/// [xmlcheck check first child]
pugi::xml_document doc;
TTB::TheXmlCheck()->ReadFromString(doc, SHORT_DEMO);
TTB_INFO("Check first child (using relative xpath starting from root node)");
TTB::TheXmlCheck()->CheckSubNode(doc, "Child");
TTB_EXP("Child");
TTB_EXP(" Id: 1001");
TTB_EXP(" Contents of child 1");
/// [xmlcheck check first child]
/// [xmlcheck check second child]
TTB_INFO("\nCheck only second child (using separate call to NodeFromXPath with relative xpath)");
pugi::xml_node subNode = TTB::TheXmlCheck()->NodeFromXPath(doc.document_element(), "Child[2]");
TTB::TheXmlCheck()->CheckNode(subNode);
TTB_EXP("Child");
TTB_EXP(" Id: 1002");
TTB_EXP(" Contents of child 2");
TTB_INFO("\nCheck only second child (using absolute xpath)");
TTB::TheXmlCheck()->CheckSubNode(doc, "/SomeNode/Child[2]");
TTB_EXP("Child");
TTB_EXP(" Id: 1002");
TTB_EXP(" Contents of child 2");
/// [xmlcheck check second child]
/// [xmlcheck check first three childs]
TTB_INFO("\nCheck the first three childs");
TTB::TheXmlCheck()->CheckSubNodeWithMaxChilds(3, doc, "/SomeNode");
TTB_EXP("SomeNode");
TTB_EXP(" Child");
TTB_EXP(" Id: 1001");
TTB_EXP(" Contents of child 1");
TTB_EXP(" Child");
TTB_EXP(" Id: 1002");
TTB_EXP(" Contents of child 2");
TTB_EXP(" Child");
TTB_EXP(" Id: 1003");
TTB_EXP(" Contents of child 3");
/// [xmlcheck check first three childs]
/// [xmlcheck check last child]
TTB_INFO("\nCheck last child");
TTB::TheXmlCheck()->CheckSubNode(doc, "Child[last()]");
TTB_EXP("Child");
TTB_EXP(" Id: 1005");
TTB_EXP(" Contents of child 5");
/// [xmlcheck check last child]
/// [xmlcheck check child with attribute value]
TTB_INFO("\nCheck child with attribute Id=1003");
TTB::TheXmlCheck()->CheckSubNode(doc, "Child[@Id='1003']");
TTB_EXP("Child");
TTB_EXP(" Id: 1003");
TTB_EXP(" Contents of child 3");
TTB_INFO("\nCheck blue subchild of 4th child");
TTB::TheXmlCheck()->CheckSubNode(doc, "Child[4]/SubChild[@color='green']");
TTB_EXP("SubChild");
TTB_EXP(" color: green");
TTB_EXP(" Green contents");
TTB_INFO("\nCheck not existing black subchild of 4th child");
TTB::TheXmlCheck()->CheckSubNode(doc, "Child[4]/SubChild[@color='black']");
// No output, nothing to verify
/// [xmlcheck check child with attribute value]
}}
//-----------------------------------------------------------------------------
TTB_BOOST_TEST_CASE(ShortDemo_IgnoreNodesOrAttributes)
{
/// [xmlcheck ignore nodes xml sample]
static const std::string SHORT_DEMO = R"(
<SomeLogEntry>
<this>0x24315683</this>
<Child Id="1001" date="01.04.2015" time="23:55:00">
<Counter>13</Counter>
</Child>
<ComplexChild>
<UninterestingDetails>Details not shown here</UninterestingDetails>
</ComplexChild>
</SomeLogEntry>
)";
/// [xmlcheck ignore nodes xml sample]
/// [xmlcheck ignore nodes check all]
// Simply check all data
pugi::xml_document doc;
TTB::TheXmlCheck()->ReadFromString(doc, SHORT_DEMO);
TTB::TheXmlCheck()->CheckNode(doc);
TTB_EXP("SomeLogEntry");
TTB_EXP(" this");
TTB_EXP(" 0x24315683");
TTB_EXP(" Child");
TTB_EXP(" Id: 1001");
TTB_EXP(" date: 01.04.2015");
TTB_EXP(" time: 23:55:00");
TTB_EXP(" Counter");
TTB_EXP(" 13");
TTB_EXP(" ComplexChild");
TTB_EXP(" UninterestingDetails");
TTB_EXP(" Details not shown here");
/// [xmlcheck ignore nodes check all]
/// [xmlcheck ignore nodes configure]
// Ignore typical attributes that contain "random" values which cannot be verified
TTB::TheXmlCheck()->IgnoreAttribute("date");
TTB::TheXmlCheck()->IgnoreAttribute("time");
TTB::TheXmlCheck()->IgnoreNode("this");
// Ignore parts of xml tree you are not interested in
TTB::TheXmlCheck()->IgnoreNode("ComplexChild");
/// [xmlcheck ignore nodes configure]
/// [xmlcheck ignore nodes check]
// Now check only interesting contents
TTB::TheXmlCheck()->CheckNode(doc);
TTB_EXP("SomeLogEntry");
TTB_EXP(" Child");
TTB_EXP(" Id: 1001");
TTB_EXP(" Counter");
TTB_EXP(" 13");
/// [xmlcheck ignore nodes check]
}}
//-----------------------------------------------------------------------------
TTB_BOOST_TEST_CASE(ShortDemo_CheckPointerValues)
{
/// [xmlcheck pointer values sample data]
static const std::string SHORT_DEMO = R"(
<SomeLogEntry>
<this>0x24315683</this>
<Child Id="1001" pSomething="0x24315683" pSomethingElse="0" />
</SomeLogEntry>
)";
/// [xmlcheck pointer values sample data]
/// [xmlcheck pointer values configure]
// Sometimes pointer values have to be checked if they are set or not.
// The exact pointer value is not relevant (and cannot be expected to be
// the same in repeated executions)
TTB::TheXmlCheck()->UseAsPointerAttribute("pSomething");
TTB::TheXmlCheck()->UseAsPointerAttribute("pSomethingElse");
TTB::TheXmlCheck()->UseAsPointerNode("this");
/// [xmlcheck pointer values configure]
/// [xmlcheck pointer values check]
// Now check only interesting contents
pugi::xml_document doc;
TTB::TheXmlCheck()->ReadFromString(doc, SHORT_DEMO);
TTB::TheXmlCheck()->CheckNode(doc);
TTB_EXP("SomeLogEntry");
TTB_EXP(" this");
TTB_EXP(" exists");
TTB_EXP(" Child");
TTB_EXP(" Id: 1001");
TTB_EXP(" pSomething: exists");
TTB_EXP(" pSomethingElse: 0");
/// [xmlcheck pointer values check]
}}
//-----------------------------------------------------------------------------
TTB_BOOST_TEST_CASE(ShortDemo_ErrorHandlingWrongXmlString)
{
static const std::string WRONG_XML_STRING = R"(
<SomeNode attrA="4">
<SubNodeB>Some content of SubNodeB</WrongName>
<SubNodeC> corrupt data</SubNodeC
</SomeNode>)";
pugi::xml_document doc;
TTB_INFO("Try to read xml string with wrong end tag");
TTB::TheXmlCheck()->ReadFromString(doc, WRONG_XML_STRING);
TTB_EXP("Parse error: Start-end tags mismatch, character pos= 74");
TTB_INFO("\nNevertheless some contents are available:");
TTB::TheXmlCheck()->CheckNode(doc);
TTB_EXP("SomeNode");
TTB_EXP(" attrA: 4");
TTB_EXP(" SubNodeB");
TTB_EXP(" Some content of SubNodeB");
}}
//-----------------------------------------------------------------------------
TTB_BOOST_TEST_CASE(ShortDemo_ErrorHandlingXmlFileNotExisting)
{
pugi::xml_document doc;
TTB_INFO("Try to read from not existing xml file");
TTB::TheXmlCheck()->ReadFromFile(doc, "C:\\NotExistingXmlFile");
TTB_EXP("Parse error: File was not found, character pos= 0");
TTB_INFO("\nNo contents are available:");
TTB::TheXmlCheck()->CheckNode(doc);
}}
//-----------------------------------------------------------------------------
BOOST_AUTO_TEST_SUITE_END()