2018-04-18 Coding to generate data for Allure report

Step 1 Identify the information needed

For each test case execution, we need to collect below information:

  • start-time & end-time of entire execution
  • start-time, end-time & duration of each test case
  • name of the test script
  • execution status. 111=pass, 100=Fail, 000=Error, 101=Block
  • comment
  • location of log-files
  • feature name, can be abstracted from script name

Step 2 Decide the format of the information

  • start-time, end-time, duration, in seconds since 1970-01-01
  • script name, of type string
  • execution status, of type string
  • comment, location of logs, feature, of type string

Step 3 Collect the information

  • List all the sub-folders of current folder
    import os
    #list all the folders in this folder
    target_folder = "./logs"
    
    arr_dir = []
    for root, dirs, files in os.walk(target_folder):
        for name in dirs:
            arr_dir.append(name)
  • Build path to some log-file, then read contents of the file
    stdout_path = os.path.join(target_folder, dir_name, "stdout.txt")
    stdout_f = open(stdout_path, 'r')
    stdout_contents = stdout_f.readlines() 
  • Get the first/last line of the log
    first_line = stdout_contents[0].strip()
    last_line = stdout_contents[-1].strip()
  • Get the first/last line of the log
    first_line = stdout_contents[0].strip()
    last_line = stdout_contents[-1].strip()
  • Convert time-string like 2018-04-18 07-33-08 into seconds since 1970-01-01
    import time

    #convert string to time
    time_str = "2018-04-18 07-33-08"
    the_tick = time.strptime(the_tick, '%Y-%m-%d %H-%M-%S')

    #get time-stamp
    the_tick = time.mktime(the_tick)
  • Decide the execution result of the test case, using log content
    def abstract_script_result_from_log_line(the_line):    
        if "Result = Pass" in the_line:
            return "Pass"
        if "Result = Fail" in the_line:
            return "Fail"
        else:
            return "Error"

Step 4 Write information into XML format

    from xml.etree.ElementTree import Element, SubElement
    from xml.etree.ElementTree import Comment, tostring, ElementTree

    #build xml-element        
    result = Element('result')
    start_time = SubElement(result, 'startTime')
    start_time.text = str(script_start_time)
        
    end_time = SubElement(result, 'endTime')
    end_time.text = str(script_end_time)
        
    duration = SubElement(result, 'duration')
    duration.text = str(script_duration)[0:6]
        
    name = SubElement(result, 'name')
    name.text = script_name.strip()
        
    status = SubElement(result, 'status')
    status.text = script_status_code
        
    comment = SubElement(result, 'comment')
    comment.text = script_comment
        
    log_file = SubElement(result, 'logFile')
    log_file.text = script_log_folder
        
    class_name = SubElement(result, 'featureName')
    class_name.text = script_feature_name
    
    #write to result xml file
    meta_data = "results.xml"
    results_xml = open(meta_data, 'w')
    
    #global start-time
    results_xml.write('<results>')
    results_xml.write('<startTime>')
    results_xml.write(str(global_start_time))
    results_xml.write('</startTime>')

    results_xml.write(tostring(result))
    results_xml.write('\n')

    #global end-time
    results_xml.write('<endTime>')
    results_xml.write(str(global_end_time))
    results_xml.write('</endTime>')
    results_xml.write('</results>')

Step 5 Define a script file to convert the XML content into J-Unit format

  • Define the schema of the XML file(xlst.xsl)
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8"
        indent="yes" />
    <xsl:strip-space elements="*" />
    <xsl:template match="results">
        <testsuites>
            <testsuite tests="{count(result/status)}" passed="{count(result[status='111'])}"
                failure="{count(result[status='100'])}" skipped="{count(result[status='101'])}"
                error="{count(result[status='000'])}" time="{endTime - startTime}">
                <xsl:for-each select="result[status='111']">
                    <testcase name="{name}" classname="{featureName}" result="{status}"
                        comments="{comment}" time="{duration}">
                        <passed />
                    </testcase>
                </xsl:for-each>
                <xsl:for-each select="result[status='000']">
                    <testcase name="{name}" classname="{featureName}" result="{status}"
                        comments="{comment}" time="{duration}">
                        <failure message="{failReason}"></failure>
                        <error />
                    </testcase>

                </xsl:for-each>
                <xsl:for-each select="result[status='100']">
                    <testcase name="{name}" classname="{featureName}" result="{status}"
                        comments="{comment}" time="{duration}">
                        <failure message="{failReason}"></failure>
                        <failure />
                    </testcase>
                </xsl:for-each>
                <xsl:for-each select="result[status='101']">
                    <testcase name="{name}" result="{status}" comments="{comment}">
                        <skipped message="Test never ran"></skipped>
                        <skipped />
                    </testcase>
                </xsl:for-each>
            </testsuite>
        </testsuites>
    </xsl:template>
</xsl:stylesheet>
  • Use Python to read and convert the XML based on the schema
from lxml import etree, objectify
import os.path
import sys

def generateJUnit(metadata):
        parser = etree.XMLParser(remove_blank_text=True)
        tree = etree.parse(metadata, parser)
        root = tree.getroot()
        for elem in root.getiterator():
            if not hasattr(elem.tag, 'find'): continue  # (1)
            i = elem.tag.find('}')
            if i >= 0:
                elem.tag = elem.tag[i + 1:]
        objectify.deannotate(root, cleanup_namespaces=True)
        tree.write(metadata,pretty_print=True, xml_declaration=True, encoding='UTF-8')
        dom = etree.parse(metadata)
        xslt = etree.parse("XLST.xsl")
        transform = etree.XSLT(xslt)
        newdom = transform(dom)
        str = etree.tostring(newdom, pretty_print=True)
        print("Generating TestResults.xml under TestEnvironment")
        with open("TestEnvironment\TestResults.xml","w")as fp:
            fp.write(str)

if __name__ == '__main__':
    metadata = sys.argv[1]
    generateJUnit(metadata)
  • Invoke the python script file
    python JUnitResultGenerator.py

Step 6 Use Allure command-line to generate the HTML report

allure-commandline\bin\allure.bat generate TestEnvironment -c -o allure-results

References:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末橱野,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子善玫,更是在濱河造成了極大的恐慌水援,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茅郎,死亡現(xiàn)場(chǎng)離奇詭異蜗元,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)系冗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門奕扣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人掌敬,你說我怎么就攤上這事惯豆〕卮牛” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵楷兽,是天一觀的道長(zhǎng)框仔。 經(jīng)常有香客問我,道長(zhǎng)拄养,這世上最難降的妖魔是什么离斩? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮瘪匿,結(jié)果婚禮上跛梗,老公的妹妹穿的比我還像新娘。我一直安慰自己棋弥,他們只是感情好核偿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著顽染,像睡著了一般漾岳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上粉寞,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天尼荆,我揣著相機(jī)與錄音,去河邊找鬼唧垦。 笑死捅儒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的振亮。 我是一名探鬼主播巧还,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼坊秸!你這毒婦竟也來了麸祷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤褒搔,失蹤者是張志新(化名)和其女友劉穎阶牍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體站超,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡荸恕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了死相。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片融求。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖算撮,靈堂內(nèi)的尸體忽然破棺而出生宛,到底是詐尸還是另有隱情县昂,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布陷舅,位于F島的核電站倒彰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏莱睁。R本人自食惡果不足惜待讳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仰剿。 院中可真熱鬧创淡,春花似錦、人聲如沸南吮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽部凑。三九已至露乏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間涂邀,已是汗流浹背瘟仿。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留必孤,地道東北人猾骡。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像敷搪,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子幢哨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容