Skip to content

Commit

Permalink
Merge pull request #14 from cclauss/pre-release
Browse files Browse the repository at this point in the history
Cleanup to prepare for a release
  • Loading branch information
Trott authored Sep 26, 2019
2 parents ee5c20b + 1f04dca commit d9c94d4
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 143 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ env:
install: pip install flake8 junit-xml yamlish
before_script: flake8 . --count --select=E9,F --show-source --statistics
script:
- python tap2junit/tap13.py
- python -m tap2junit -i test/fixtures/${FILENAME}.tap -o test/output/${FILENAME}.xml
- cat test/output/${FILENAME}.xml
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ verify_ssl = true
name = "pypi"

[packages]
yamlish = "*"
junit-xml = "*"
yamlish = "*"

[dev-packages]

Expand Down
60 changes: 0 additions & 60 deletions Pipfile.lock

This file was deleted.

20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
A utility that converts [TAP version 13](https://testanything.org/) to [JUnit](https://junit.org/junit5/). That's it.

The syntax expected is currently pretty custom-tailored for use at https://ci.nodejs.org.

Improvements welcome.

To install:

`pip install tap2junit`

To run:

`tap2junit -i file.tap -o file.xml`

Suggested code hygiene:
```
$ flake8 --max-line-length=88 .
$ isort -rc .
$ black .
```
14 changes: 0 additions & 14 deletions README.rst

This file was deleted.

2 changes: 0 additions & 2 deletions setup.cfg

This file was deleted.

52 changes: 24 additions & 28 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,35 @@
# coding: utf-8

# Always prefer setuptools over distutils
from setuptools import setup
# To use a consistent encoding
from codecs import open
from os import path

import setuptools

here = path.abspath(path.dirname(__file__))

# Get the long description from the README file
with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
long_description = f.read()
with open(path.join(here, "README.md")) as in_file:
long_description = in_file.read()

setup(
name='tap2junit',
version='0.1.5',
description='Tap13 to jUnit',
setuptools.setup(
name="tap2junit",
version="0.1.5",
description="Tap13 to jUnit",
long_description=long_description,
url='https://github.com/jbergstroem/tap2junit',
author='Johan Bergström',
author_email='bugs@bergtroem.nu',
url="https://github.com/nodejs/tap2junit",
author="Node.js contributors",
author_email="cclauss@me.com",
classifiers=[
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'Topic :: Software Development :: Build Tools',
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)",
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Topic :: Software Development :: Build Tools",
],
keywords='tap13 junit',
packages=['tap2junit'],
install_requires=['yamlish', 'junit-xml'],
entry_points={
'console_scripts': [
'tap2junit = tap2junit.__main__:main',
],
},
keywords="tap13 junit",
packages=["tap2junit"],
install_requires=["junit-xml", "yamlish"],
entry_points={"console_scripts": ["tap2junit = tap2junit.__main__:main"]},
)
45 changes: 29 additions & 16 deletions tap2junit/__main__.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
import argparse
import os
import platform
from junit_xml import TestSuite, TestCase

from junit_xml import TestCase, TestSuite
from tap2junit.tap13 import TAP13 as tap13


def map_yaml_to_junit(test):
yaml = test.yaml or {}
# Even though the name is `duration_ms` the value is in seconds.
elapsed_sec = yaml.get('duration_ms', None)
elapsed_sec = yaml.get("duration_ms", None)
t = TestCase(test.description, classname=None, elapsed_sec=elapsed_sec)
if test.result == 'ok':
if test.directive in ['SKIP', 'TODO']:
if test.result == "ok":
if test.directive in ("SKIP", "TODO"):
t.add_skipped_info(test.comment)
else:
t.stdout = test.comment

elif test.result == 'not ok':
err_code = yaml.get('exitcode', 0)
err_severity = yaml.get('severity', '')
err_output = yaml.get('stack', '')
elif test.result == "not ok":
err_code = yaml.get("exitcode", 0)
err_severity = yaml.get("severity", "")
err_output = yaml.get("stack", "")
error_message = "{} ({})".format(err_severity, err_code)
if err_severity == 'crashed' or err_code < 0:
if err_code < 0 or err_severity == "crashed":
t.add_error_info(error_message, err_output, err_code)
else:
t.add_failure_info(error_message, err_output, err_code)
Expand All @@ -40,16 +41,28 @@ def convert(in_file, out_file):
input_file = os.path.splitext(in_file.name)[0]
data = in_file.read()
result = parse(input_file, data)
TestSuite.to_file(out_file, [result], prettyprint=True, encoding='utf-8')
TestSuite.to_file(out_file, [result], prettyprint=True, encoding="utf-8")


def main():
arg_parser = argparse.ArgumentParser('tap2junit')
arg_parser.add_argument('--input', '-i', type=argparse.FileType('r'), help='path to tap13 file', required=True)
arg_parser.add_argument('--output', '-o', type=argparse.FileType('w'), help='output file name', required=True)
args = arg_parser.parse_args()
convert(args.input, args.output)
arg_parser = argparse.ArgumentParser("tap2junit")
arg_parser.add_argument(
"--input",
"-i",
type=argparse.FileType("r"),
help="path to tap13 file",
required=True,
)
arg_parser.add_argument(
"--output",
"-o",
type=argparse.FileType("w"),
help="output file name",
required=True,
)
args = arg_parser.parse_args()
convert(args.input, args.output)


if __name__ == "__main__":
main()
main()
55 changes: 36 additions & 19 deletions tap2junit/tap13.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from __future__ import print_function
# Copyright 2013, Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
Expand All @@ -20,12 +19,14 @@
from __future__ import print_function

import re

import yamlish

try:
from StringIO import StringIO
except ImportError:
from io import StringIO

import yamlish


try:
basestring
Expand All @@ -34,15 +35,23 @@


RE_VERSION = re.compile(r"^\s*TAP version 13\s*$")
RE_PLAN = re.compile(r"^\s*(?P<start>\d+)\.\.(?P<end>\d+)\s*(#\s*(?P<explanation>.*))?\s*$")
RE_TEST_LINE = re.compile(r"^\s*(?P<result>(not\s+)?ok)\s*(?P<id>\d+)?\s*(?P<description>[^#]+)?\s*(#\s*(?P<directive>TODO|SKIP)?\s*(?P<comment>.+)?)?\s*$", re.IGNORECASE)
RE_PLAN = re.compile(
r"^\s*(?P<start>\d+)\.\.(?P<end>\d+)\s*(#\s*(?P<explanation>.*))?\s*$"
)
RE_TEST_LINE = re.compile(
(
r"^\s*(?P<result>(not\s+)?ok)\s*(?P<id>\d+)?\s*(?P<description>[^#]+)"
r"?\s*(#\s*(?P<directive>TODO|SKIP)?\s*(?P<comment>.+)?)?\s*$"
),
re.IGNORECASE,
)
RE_EXPLANATION = re.compile(r"^\s*#\s*(?P<explanation>.+)?\s*$")
RE_YAMLISH_START = re.compile(r"^\s*---.*$")
RE_YAMLISH_END = re.compile(r"^\s*\.\.\.\s*$")


class Test(object):
def __init__(self, result, id, description = None, directive = None, comment = None):
def __init__(self, result, id, description=None, directive=None, comment=None):
self.result = result
self.id = id
self.description = description
Expand All @@ -62,7 +71,6 @@ def __init__(self):
self.__tests_counter = 0
self.tests_planned = None


def _parse(self, source):
seek_version = True
seek_plan = False
Expand Down Expand Up @@ -116,11 +124,11 @@ def _parse(self, source):
m = RE_PLAN.match(line)
if m:
d = m.groupdict()
self.tests_planned = int(d.get('end', 0))
self.tests_planned = int(d.get("end", 0))
seek_plan = False

# Stop processing if tests were found before the plan
# if plan is at the end, it must be the last line -> stop processing
# if plan is at the end, it must be last line -> stop processing
if self.__tests_counter > 0:
break

Expand All @@ -129,15 +137,22 @@ def _parse(self, source):
if m:
self.__tests_counter += 1
t_attrs = m.groupdict()
if t_attrs['id'] is None:
t_attrs['id'] = self.__tests_counter
t_attrs['id'] = int(t_attrs['id'])
if t_attrs['id'] < self.__tests_counter:
if t_attrs["id"] is None:
t_attrs["id"] = self.__tests_counter
t_attrs["id"] = int(t_attrs["id"])
if t_attrs["id"] < self.__tests_counter:
raise ValueError("Descending test id on line: %r" % line)
# according to TAP13 specs, missing tests must be handled as 'not ok'
# here we add the missing tests in sequence
while t_attrs['id'] > self.__tests_counter:
self.tests.append(Test('not ok', self.__tests_counter, comment = 'DIAG: Test %s not present' % self.__tests_counter))
# according to TAP13 specs, missing tests must be handled as
# 'not ok'. Here we add the missing tests in sequence
while t_attrs["id"] > self.__tests_counter:
self.tests.append(
Test(
"not ok",
self.__tests_counter,
comment="DIAG: Test %s not present"
% self.__tests_counter,
)
)
self.__tests_counter += 1
t = Test(**t_attrs)
self.tests.append(t)
Expand All @@ -150,8 +165,9 @@ def _parse(self, source):

if len(self.tests) != self.tests_planned:
for i in range(len(self.tests), self.tests_planned):
self.tests.append(Test('not ok', i+1, comment = 'DIAG: Test %s not present'))

self.tests.append(
Test("not ok", i + 1, comment="DIAG: Test %s not present")
)

def parse(self, source):
if isinstance(source, basestring):
Expand Down Expand Up @@ -199,6 +215,7 @@ def parse(self, source):
t.parse(input)

import pprint

for test in t.tests:
print(test.result, test.id, test.description, "#", test.directive, test.comment)
pprint.pprint(test.yaml_buffer)
Expand Down
1 change: 0 additions & 1 deletion test/fixtures/test2.xml

This file was deleted.

Empty file added test/output/.empty
Empty file.
2 changes: 0 additions & 2 deletions test/output/.gitignore

This file was deleted.

0 comments on commit d9c94d4

Please sign in to comment.