make_test_output.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. """Gather output from test runs and create an XML file in JUnit format.
  2. The output files from the individual tests have been written in a directory
  3. structure like:
  4. $DIR/joblog (--joblog from "parallel")
  5. $DIR/logs/1/cpp/stdout
  6. $DIR/logs/1/cpp/stderr
  7. $DIR/logs/1/csharp/stdout
  8. $DIR/logs/1/csharp/stderr
  9. $DIR/logs/1/java_jdk7/stdout
  10. $DIR/logs/1/java_jdk7/stderr
  11. etc.
  12. This script bundles them into a single output XML file so Jenkins can show
  13. detailed test results.
  14. """
  15. import os;
  16. import sys;
  17. from yattag import Doc
  18. from collections import defaultdict
  19. def readtests(basedir):
  20. tests = defaultdict(dict)
  21. # Sample input (note: separators are tabs).
  22. #
  23. # Seq Host Starttime Runtime Send Receive Exitval Signal Command
  24. # 1 : 1456263838.313 0.005 0 0 0 0 echo A
  25. with open(basedir + "/joblog") as jobs:
  26. firstline = next(jobs)
  27. for line in jobs:
  28. values = line.split("\t")
  29. name = values[8].split()[-1]
  30. test = tests[name]
  31. test["name"] = name
  32. test["time"] = values[3]
  33. exitval = values[6]
  34. if int(exitval):
  35. # We don't have a more specific message. User should look at stderr.
  36. test["failure"] = "TEST FAILURE"
  37. else:
  38. test["failure"] = False
  39. for testname in os.listdir(basedir + "/logs/1"):
  40. test = tests[testname]
  41. with open(basedir + "/logs/1/" + testname + "/stdout") as f:
  42. test["stdout"] = f.read()
  43. with open(basedir + "/logs/1/" + testname + "/stderr") as f:
  44. test["stderr"] = f.read()
  45. # The cpp test is special since it doesn't run under parallel so doesn't show
  46. # up in the job log.
  47. tests["cpp"]["name"] = "cpp"
  48. with open(basedir + '/logs/1/cpp/build_time', 'r') as f:
  49. tests["cpp"]["time"] = f.read().strip()
  50. tests["cpp"]["failure"] = False
  51. ret = tests.values()
  52. ret.sort(key=lambda x: x["name"])
  53. return ret
  54. def genxml(tests):
  55. doc, tag, text = Doc().tagtext()
  56. with tag("testsuites"):
  57. with tag("testsuite", name="Protobuf Tests"):
  58. for test in tests:
  59. with tag("testcase", name=test["name"], classname=test["name"],
  60. time=test["time"]):
  61. with tag("system-out"):
  62. text(test["stdout"])
  63. with tag("system-err"):
  64. text(test["stderr"])
  65. if test["failure"]:
  66. with tag("failure"):
  67. text(test["failure"])
  68. return doc.getvalue()
  69. sys.stderr.write("make_test_output.py: writing XML from directory: " +
  70. sys.argv[1] + "\n");
  71. print genxml(readtests(sys.argv[1]))