背景
関わっているプロジェクトでは、CodeBuildを使ってJunitテストの実行結果をレポートとして出力しています。
しかし、XML形式であり、ファイルがテストクラスごとに作成されるため、一覧性が悪いという問題があります。
ブラウザ上で結果の一覧を見ることもできますが、Stacktraceなど詳細を確認したい場合には、一覧からリンクで詳細を開かないといけません。
この問題を解決するために、出力されたXMLファイルをExcelファイルに変換するpythonプログラムを作成しました。
XMLをExcelに変換する
この記事では、レポートファイルの収集方法などは省略し、XMLの内容を抽出してExcelとして出力する部分に焦点を当てます。
変換元のファイル
変換元のXMLファイルはこのような内容になっています。
<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="xxx.yyy.zzz.SampleTest" tests="3" skipped="0" failures="2" errors="0" timestamp="2024-05-20T22:51:25" hostname="abcdefg" time="0.077">
<properties/>
<testcase name="test1()" classname="xxx.yyy.zzz.SampleTest" time="0.024"/>
<testcase name="test2()" classname="xxx.yyy.zzz.SampleTest" time="0.021">
<failure message="エラーメッセージ" type="発生したException">スタックトレースの内容</failure>
</testcase>
<testcase name="test3()" classname="xxx.yyy.zzz.SampleTest" time="0.032">
<failure message="エラーメッセージ" type="発生したException">スタックトレースの内容</failure>
</testcase>
<system-out><![CDATA[system-outの内容]]></system-out>
<system-err><![CDATA[system-erroの内容]]></system-err>
</testsuite>
xmltodictでXMLを辞書に変換する
まず、xmltodictをインストールします。
pip install xmltodict
xmltodictを使ってXMLを辞書に変換します。
import xmltodict
with open('XMLファイルのパス') as f:
xml = f.read()
dic = xmltodict.parse(xml)
print(dic)
変換してできた辞書の内容はこのようになります。
{
'testsuite': {
'@name': 'xxx.yyy.zzz.SampleTest',
'@tests': '3',
'@skipped': '0',
'@failures': '2',
'@errors': '0',
'@timestamp': '2024-05-20T22: 51: 25',
'@hostname': 'abcdefg',
'@time': '0.077',
'properties': None,
'testcase': [
{
'@name': 'test1()',
'@classname': 'xxx.yyy.zzz.SampleTest',
'@time': '0.024'
},
{
'@name': 'test2()',
'@classname': 'xxx.yyy.zzz.SampleTest',
'@time': '0.021',
'failure': {
'@message': 'エラーメッセージが出力される',
'@type': '発生したException',
'#text': 'スタックトレースの内容'
}
},
{
'@name': 'test3()',
'@classname': 'xxx.yyy.zzz.SampleTest',
'@time': '0.032',
'failure': {
'@message': 'エラーメッセージが出力される',
'@type': '発生したException',
'#text': 'スタックトレースの内容'
}
}
],
'system-out': 'system-outの内容',
'system-err': 'system-erroの内容'
}
}
pandasでExcelに変換する
今回はpandasを使ってExcel出力するため、pandasをインストールしておきます。
pip install pandas
なお、pandasでxlsx形式で取得するときにはopenpyxlが使われるため、これもインストールしておきます。
pip install openpyxl
Excel出力するために、testsuite.testcase
から以下の内容を抽出し、行データ(配列)に変換します。
@classname
@name
@time
failure.#text
error.#text
testcases = [
[
testcase['@classname'],
testcase['@name'],
testcase['@time'],
testcase['failure']['#text'] if 'failure' in testcase else None,
testcase['error']['#text'] if 'error' in testcase else None
] for testcase in dic['testsuite']['testcase']
]
できた配列をpandasのDataFrameオブジェクトに変換します。
import pandas as pd
df = pd.DataFrame(testcases)
print(df)
以下がDataFrameオブジェクトの内容です。
0 1 2 3 4
0 xxx.yyy.zzz.SampleTest test1() 0.024 None None
1 xxx.yyy.zzz.SampleTest test2() 0.021 スタックトレースの内容 None
2 xxx.yyy.zzz.SampleTest test3() 0.032 スタックトレースの内容 None
この内容がExcelに出力されますが、行ヘッダ、列ヘッダがわかりづらいため、以下のように修正します。
df = pd.DataFrame(testcases,
# 列ヘッダ:'classname'、'name'、'time'、'failure'、'error'にする
columns=['classname', 'name', 'time', 'failure', 'error'])
# 行ヘッダ:先頭を1にする
df.index += 1
print(df)
最終的な出力結果はこのようになります。
classname name time failure error
1 xxx.yyy.zzz.SampleTest test1() 0.024 None None
2 xxx.yyy.zzz.SampleTest test2() 0.021 スタックトレースの内容 None
3 xxx.yyy.zzz.SampleTest test3() 0.032 スタックトレースの内容 None
最後にExcelファイルに出力します。
df.to_excel('出力先ファイルのパス')
補足
今回は1ファイルの内容だけをExcel出力しましたが、実際のレポートは複数ファイルになっているため、それをまとめて1つのExcelファイルに出力するには、少し改良が必要となります。