Browse Source

Update for XML output (Junit like)

Brian Aker 12 years ago
parent
commit
cd486be0d9
10 changed files with 154 additions and 48 deletions
  1. 1 4
      libtest/collection.cc
  2. 3 3
      libtest/collection.h
  3. 64 19
      libtest/formatter.cc
  4. 17 3
      libtest/formatter.hpp
  5. 12 6
      libtest/framework.cc
  6. 21 9
      libtest/framework.h
  7. 1 1
      libtest/get.h
  8. 2 0
      libtest/http.hpp
  9. 32 2
      libtest/main.cc
  10. 1 1
      libtest/skiptest.cc

+ 1 - 4
libtest/collection.cc

@@ -38,7 +38,7 @@
 
 #include <libtest/common.h>
 
-static test_return_t runner_code(Framework* frame,
+static test_return_t runner_code(libtest::Framework* frame,
                                  test_st* run, 
                                  libtest::Timer& _timer)
 { // Runner Code
@@ -92,8 +92,6 @@ Collection::Collection(Framework* frame_arg,
 
 test_return_t Collection::exec()
 {
-  Out << "Collection: " << _name;
-
   if (test_success(_frame->runner()->pre(_pre, _frame->creators_ptr())))
   {
     for (test_st *run= _tests; run->name; run++)
@@ -106,7 +104,6 @@ test_return_t Collection::exec()
       }
       _total++;
 
-
       test_return_t return_code;
       try 
       {

+ 3 - 3
libtest/collection.h

@@ -40,7 +40,7 @@
 
 #include <libtest/timer.hpp>
 
-class Framework;
+namespace { class Framework; }
 
 
 /**
@@ -57,7 +57,7 @@ namespace libtest {
 
 class Collection {
 public:
-  Collection(Framework*, collection_st*);
+  Collection(libtest::Framework*, collection_st*);
 
   test_return_t exec();
 
@@ -96,7 +96,7 @@ private:
   test_callback_fn *_pre;
   test_callback_fn *_post;
   struct test_st *_tests;
-  Framework* _frame;
+  libtest::Framework* _frame;
   uint32_t _success;
   uint32_t _skipped;
   uint32_t _failed;

+ 64 - 19
libtest/formatter.cc

@@ -37,6 +37,9 @@
 #include <config.h>
 
 #include <libtest/common.h>
+
+#include <iostream>
+#include <fstream>
   
 namespace libtest {
 
@@ -86,62 +89,104 @@ private:
 };
 
 Formatter::Formatter(const std::string& arg) :
-  _suite_name(arg),
-  _current_testcase(NULL)
+  _suite_name(arg)
 {
 }
 
 Formatter::~Formatter()
 {
-  for (TestCases::iterator iter= testcases.begin(); iter != testcases.end(); ++iter)
+  for (TestCases::iterator iter= _testcases.begin(); iter != _testcases.end(); ++iter)
   {
     delete *iter;
   }
 }
 
+TestCase* Formatter::current()
+{
+  return _testcases.back();
+}
+
 void Formatter::skipped()
 {
-  assert(_current_testcase);
-  _current_testcase->result(TEST_SKIPPED);
-  Out << "\tTesting " << _current_testcase->name() <<  "\t\t\t\t\t" << "[ " << test_strerror(_current_testcase->result()) << " ]";
+  current()->result(TEST_SKIPPED);
+  Out << "\t" << name() << "." << current()->name() <<  "\t\t\t\t\t" << "[ " << test_strerror(current()->result()) << " ]";
 
   reset();
 }
 
 void Formatter::failed()
 {
-  assert(_current_testcase);
-  _current_testcase->result(TEST_FAILURE);
+  assert(current());
+  current()->result(TEST_FAILURE);
 
-  Out << "\tTesting " << _current_testcase->name() <<  "\t\t\t\t\t" << "[ " << test_strerror(_current_testcase->result()) << " ]";
+  Out << "\t" << name() << "." << current()->name() <<  "\t\t\t\t\t" << "[ " << test_strerror(current()->result()) << " ]";
 
   reset();
 }
 
 void Formatter::success(const libtest::Timer& timer_)
 {
-  assert(_current_testcase);
-  _current_testcase->result(TEST_SUCCESS, timer_);
+  assert(current());
+  current()->result(TEST_SUCCESS, timer_);
 
-  Out << "\tTesting " 
-    << _current_testcase->name()
+  Out << "\t"
+    << name() << "."
+    << current()->name()
     <<  "\t\t\t\t\t" 
-    << _current_testcase->timer() 
-    << " [ " << test_strerror(_current_testcase->result()) << " ]";
+    << current()->timer() 
+    << " [ " << test_strerror(current()->result()) << " ]";
 
   reset();
 }
 
+void Formatter::xml(libtest::Framework& framework_, std::ofstream& output)
+{
+  output << "<testsuites name=\"" << framework_.name() << "\">" << std::endl;
+  for (Suites::iterator framework_iter= framework_.suites().begin();
+       framework_iter != framework_.suites().end();
+       ++framework_iter)
+  {
+    output << "\t<testsuite name=\"" << (*framework_iter)->name() << "\"  classname=\"\" package=\"\">" << std::endl;
+
+    for (TestCases::iterator case_iter= (*framework_iter)->formatter()->testcases().begin();
+         case_iter != (*framework_iter)->formatter()->testcases().end();
+         ++case_iter)
+    {
+      output << "\t\t<testcase name=\"" 
+        << (*case_iter)->name() 
+        << "\" time=\"" 
+        << (*case_iter)->timer().elapsed_milliseconds() 
+        << "\">" 
+        << std::endl;
+
+      switch ((*case_iter)->result())
+      {
+        case TEST_SKIPPED:
+        output << "\t\t <skipped/>" << std::endl;
+        break;
+
+        case TEST_FAILURE:
+        output << "\t\t <failure message=\"\" type=\"\"/>"<< std::endl;
+        break;
+
+        case TEST_SUCCESS:
+        break;
+      }
+      output << "\t\t</testcase>" << std::endl;
+    }
+    output << "\t</testsuite>" << std::endl;
+  }
+  output << "</testsuites>" << std::endl;
+}
+
 void Formatter::push_testcase(const std::string& arg)
 {
   assert(_suite_name.empty() == false);
-  assert(_current_testcase == NULL);
-  _current_testcase= new TestCase(arg);
-  testcases.push_back(_current_testcase);
+  TestCase* _current_testcase= new TestCase(arg);
+  _testcases.push_back(_current_testcase);
 }
 
 void Formatter::reset()
 {
-  _current_testcase= NULL;
 }
 } // namespace libtest

+ 17 - 3
libtest/formatter.hpp

@@ -38,6 +38,8 @@
 
 #include <string>
 
+namespace libtest { class Framework; }
+
 
 namespace libtest {
 
@@ -58,14 +60,26 @@ public:
 
   void push_testcase(const std::string&);
 
+  const std::string& name() const
+  {
+    return _suite_name;
+  }
+
+  TestCases& testcases()
+  {
+    return _testcases;
+  }
+
+  static void xml(libtest::Framework&, std::ofstream&);
+
 private:
   void reset();
 
+  TestCase* current();
+
 private:
   std::string _suite_name;
-  std::vector <TestCase*> testcases;
-
-  TestCase *_current_testcase;
+  TestCases _testcases;
 };
 
 } // namespace libtest

+ 12 - 6
libtest/framework.cc

@@ -43,12 +43,12 @@
 #include <fnmatch.h>
 #include <iostream>
 
-using namespace libtest;
+namespace libtest {
 
 Framework::Framework(libtest::SignalThread& signal,
+                     const std::string& name_,
                      const std::string& only_run_arg,
                      const std::string& wildcard_arg) :
-  _collections(NULL),
   _total(0),
   _success(0),
   _skipped(0),
@@ -61,11 +61,15 @@ Framework::Framework(libtest::SignalThread& signal,
   _creators_ptr(NULL),
   _signal(signal),
   _only_run(only_run_arg),
-  _wildcard(wildcard_arg)
+  _wildcard(wildcard_arg),
+  _name(name_)
 {
   get_world(this);
+}
 
-  for (collection_st *next= _collections; next and next->name; next++)
+void Framework::collections(collection_st* collections_)
+{
+  for (collection_st *next= collections_; next and next->name; next++)
   {
     _collection.push_back(new Collection(this, next));
   }
@@ -148,9 +152,9 @@ void Framework::exec()
       _failed++;
       throw;
     }
-
-    Outn();
   }
+
+  void xml(const std::string& testsuites_name, std::ostream& output);
 }
 
 uint32_t Framework::sum_total()
@@ -226,3 +230,5 @@ test_return_t Framework::create()
 
   return rc;
 }
+
+} // namespace libtest

+ 21 - 9
libtest/framework.h

@@ -46,12 +46,22 @@
 
 #include <vector>
 
+namespace { class Collection; }
+typedef std::vector<libtest::Collection*> Suites;
+
+namespace libtest {
+
 class Framework {
 public:
 
 public:
   test_return_t create();
 
+  const std::string& name() const
+  {
+    return _name;
+  }
+
   void create(test_callback_create_fn* arg)
   {
     _create= arg;
@@ -62,10 +72,7 @@ public:
     _destroy= arg;
   }
 
-  void collections(collection_st* arg)
-  {
-    _collections= arg;
-  }
+  void collections(collection_st* arg);
 
   void set_on_error(test_callback_error_fn *arg)
   {
@@ -100,11 +107,10 @@ public:
 
   libtest::Collection& collection();
 
-  Framework(libtest::SignalThread&, const std::string&);
-
   virtual ~Framework();
 
   Framework(libtest::SignalThread&,
+            const std::string&,
             const std::string&,
             const std::string&);
 
@@ -150,11 +156,14 @@ public:
     return _failed;
   }
 
+  Suites& suites()
+  {
+    return _collection;
+  }
+
 private:
   Framework& operator=(const Framework&);
 
-  collection_st *_collections;
-
   uint32_t _total;
   uint32_t _success;
   uint32_t _skipped;
@@ -179,8 +188,11 @@ private:
   bool _socket;
   void *_creators_ptr;
   unsigned long int _servers_to_run;
-  std::vector<libtest::Collection*> _collection;
+  Suites _collection;
   libtest::SignalThread& _signal;
   std::string _only_run;
   std::string _wildcard;
+  std::string _name;
 };
+
+} // namespace libtest

+ 1 - 1
libtest/get.h

@@ -42,7 +42,7 @@ extern "C" {
 
   /* How we make all of this work :) */
   LIBTEST_API
-    void get_world(Framework *world);
+    void get_world(libtest::Framework *world);
 
 #ifdef	__cplusplus
 }

+ 2 - 0
libtest/http.hpp

@@ -36,6 +36,8 @@
 
 #pragma once
 
+#include <libtest/vchar.hpp>
+
 namespace libtest {
 namespace http {
 

+ 32 - 2
libtest/main.cc

@@ -43,6 +43,7 @@
 #include <ctime>
 #include <fnmatch.h>
 #include <iostream>
+#include <fstream>
 #include <memory>
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -58,7 +59,7 @@
 
 using namespace libtest;
 
-static void stats_print(Framework *frame)
+static void stats_print(libtest::Framework *frame)
 {
   if (frame->failed() == 0 and frame->success() == 0)
   {
@@ -87,6 +88,23 @@ int main(int argc, char *argv[])
   bool opt_quiet= false;
   std::string collection_to_run;
   std::string wildcard;
+  std::string binary_name;
+
+  const char *just_filename= rindex(argv[0], '/');
+  if (just_filename)
+  {
+    just_filename++;
+  }
+  else
+  {
+    just_filename= argv[0];
+  }
+
+  if (just_filename[0] == 'l' and just_filename[1] == 't' and  just_filename[2] == '-')
+  {
+    just_filename+= 3;
+  }
+  binary_name.append(just_filename);
 
   /*
     Valgrind does not currently work reliably, or sometimes at all, on OSX
@@ -261,7 +279,7 @@ int main(int argc, char *argv[])
         return EXIT_FAILURE;
       }
 
-      std::auto_ptr<Framework> frame(new Framework(signal, collection_to_run, wildcard));
+      std::auto_ptr<libtest::Framework> frame(new libtest::Framework(signal, binary_name, collection_to_run, wildcard));
 
       // Run create(), bail on error.
       {
@@ -303,11 +321,23 @@ int main(int argc, char *argv[])
       }
       else if (frame->success() and (frame->failed() == 0))
       {
+        Out;
         Out << "All tests completed successfully.";
       }
 
       stats_print(frame.get());
 
+      std::ofstream xml_file;
+      std::string file_name;
+      if (getenv("LIBTEST_TEMP"))
+      {
+        file_name.append(getenv("LIBTEST_TEMP"));
+      }
+      file_name.append(frame->name());
+      file_name.append(".xml");
+      xml_file.open(file_name.c_str(), std::ios::trunc);
+      libtest::Formatter::xml(*frame, xml_file);
+
       Outn(); // Generate a blank to break up the messages if make check/test has been run
     } while (exit_code == EXIT_SUCCESS and --opt_repeat);
   }

+ 1 - 1
libtest/skiptest.cc

@@ -51,7 +51,7 @@ static void *world_create(server_startup_st&, test_return_t& rc)
   return NULL;
 }
 
-void get_world(Framework *world)
+void get_world(libtest::Framework *world)
 {
   world->create(world_create);
 }

Some files were not shown because too many files changed in this diff