Add tests for timestamps, and add support for 'exists'.
[third_party/subunit] / python / subunit / _output.py
1 #!/usr/bin/env python
2 #  subunit: extensions to python unittest to get test results from subprocesses.
3 #  Copyright (C) 2013  Thomi Richards <thomi.richards@canonical.com>
4 #
5 #  Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
6 #  license at the users choice. A copy of both licenses are available in the
7 #  project source as Apache-2.0 and BSD. You may not use this file except in
8 #  compliance with one of these two licences.
9 #
10 #  Unless required by applicable law or agreed to in writing, software
11 #  distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
12 #  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
13 #  license you chose for the specific language governing permissions and
14 #  limitations under that license.
15
16 from argparse import ArgumentParser
17 import datetime
18 from sys import stdout
19
20 from subunit.v2 import StreamResultToBytes
21
22 def output_main():
23     args = parse_arguments()
24     output = get_output_stream_writer()
25     generate_bytestream(args, output)
26
27     return 0
28
29
30 def parse_arguments(args=None):
31     """Parse arguments from the command line.
32
33     If specified, args must be a list of strings, similar to sys.argv[1:].
34
35     """
36     parser = ArgumentParser(
37         prog='subunit-output',
38         description="A tool to generate a subunit result byte-stream",
39     )
40
41     common_args = ArgumentParser(add_help=False)
42     common_args.add_argument("test_id", help="""A string that uniquely
43         identifies this test.""")
44     sub_parsers = parser.add_subparsers(dest="action")
45
46     final_state = "This is a final action: No more actions may be generated " \
47         "for this test id after this one."
48
49     parser_start = sub_parsers.add_parser(
50         "start",
51         help="Start a test.",
52         parents=[common_args]
53     )
54
55     parser_pass = sub_parsers.add_parser(
56         "pass",
57         help="Pass a test. " + final_state,
58         parents=[common_args]
59     )
60
61     parser_fail = sub_parsers.add_parser(
62         "fail",
63         help="Fail a test. " + final_state,
64         parents=[common_args]
65     )
66
67     parser_skip = sub_parsers.add_parser(
68         "skip",
69         help="Skip a test. " + final_state,
70         parents=[common_args]
71     )
72
73     parser_exists = sub_parsers.add_parser(
74         "exists",
75         help="Marks a test as existing. " + final_state,
76         parents=[common_args]
77     )
78
79     return parser.parse_args(args)
80
81
82 def translate_command_name(command_name):
83     """Turn the friendly command names we show users on the command line into
84     something subunit understands.
85
86     """
87     return {
88         'start': 'inprogress',
89         'pass': 'success',
90     }.get(command_name, command_name)
91
92
93 def get_output_stream_writer():
94     return StreamResultToBytes(stdout)
95
96
97 def generate_bytestream(args, output_writer):
98     output_writer.startTestRun()
99     output_writer.status(
100         test_id=args.test_id,
101         test_status=translate_command_name(args.action),
102         timestamp=create_timestamp()
103         )
104     output_writer.stopTestRun()
105
106
107 _ZERO = datetime.timedelta(0)
108
109
110 class UTC(datetime.tzinfo):
111     """UTC"""
112     def utcoffset(self, dt):
113         return _ZERO
114     def tzname(self, dt):
115         return "UTC"
116     def dst(self, dt):
117         return _ZERO
118
119
120 utc = UTC()
121
122
123 def create_timestamp():
124     return datetime.datetime.now(utc)