B
    ؐ<[}-                 @   s   d Z ddlZddlZddlZddlZddlZddlZddlZddlm	Z	 ddl
m
Z
 ddlmZ ddlmZ ddlmZ ddlmZmZ ed	Zed
Zdd Zdd Zdd Zdd Zdd ZG dd deZG dd deZdS )aU  This plugin provides test results in the standard XUnit XML format.

It's designed for the `Jenkins`_ (previously Hudson) continuous build
system, but will probably work for anything else that understands an
XUnit-formatted XML representation of test results.

Add this shell command to your builder ::

    nosetests --with-xunit

And by default a file named nosetests.xml will be written to the
working directory.

In a Jenkins builder, tick the box named "Publish JUnit test result report"
under the Post-build Actions and enter this value for Test report XMLs::

    **/nosetests.xml

If you need to change the name or location of the file, you can set the
``--xunit-file`` option.

If you need to change the name of the test suite, you can set the
``--xunit-testsuite-name`` option.

Here is an abbreviated version of what an XML test report might look like::

    <?xml version="1.0" encoding="UTF-8"?>
    <testsuite name="nosetests" tests="1" errors="1" failures="0" skip="0">
        <testcase classname="path_to_test_suite.TestSomething"
                  name="test_it" time="0">
            <error type="exceptions.TypeError" message="oops, wrong type">
            Traceback (most recent call last):
            ...
            TypeError: oops, wrong type
            </error>
        </testcase>
    </testsuite>

.. _Jenkins: http://jenkins-ci.org/

    N)StringIO)time)saxutils)Plugin)SkipTest)force_unicodeformat_exceptionz[\000-\010\013\014\016-\037]z^(.*?)(\(.*\))$c             C   s   t d| S )z)Replaces invalid XML characters with '?'.?)CONTROL_CHARACTERSsub)value r   1lib/python3.7/site-packages/nose/plugins/xunit.pyxml_safe>   s    r   c             C   s   t | ddS )z)Escape a string for an XML CDATA section.z]]>z]]>]]&gt;<![CDATA[)r   replace)Zcdatar   r   r   escape_cdataB   s    r   c             C   sF   t | }|r6| \}}|dd\}}||| gS | ddS d S )N.   )TEST_IDmatchgroupsrsplit)ZidvalmnameZfargsheadtailr   r   r   id_splitF   s    
r   c             C   s\   t | r| j}n| jj}t | }|rT|j}|drH|tdd }d||f S |S dS )zReturns a nice name for class object or class instance.

        >>> nice_classname(Exception()) # doctest: +ELLIPSIS
        '...Exception'
        >>> nice_classname(Exception) # doctest: +ELLIPSIS
        '...Exception'

    zorg.python.core.Nz%s.%s)inspectZisclass__name__	__class__Z	getmodule
startswithlen)objZcls_namemodr   r   r   r   nice_classnameO   s    	


r$   c             C   sz   | d }|dkr| d }nNyt |}W n@ tk
rf   yt |}W n tk
r`   |jd }Y nX Y nX t|d}t|S )zReturn the exception's message.r   Nr   zUTF-8)strUnicodeEncodeErrorUnicodeErrorargsr   r   )exc_infoexcresultr   r   r   exc_messagef   s    

r,   c               @   s4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )Teec             G   s   || _ || _d S )N)	_encoding_streams)selfencodingr(   r   r   r   __init__z   s    zTee.__init__c             C   s*   t || j}x| jD ]}|| qW d S )N)r   r.   r/   write)r0   datasr   r   r   r3   ~   s    z	Tee.writec             C   s   x|D ]}|  | qW d S )N)r3   )r0   linesliner   r   r   
writelines   s    
zTee.writelinesc             C   s   x| j D ]}|  qW d S )N)r/   flush)r0   r5   r   r   r   r9      s    z	Tee.flushc             C   s   dS )NFr   )r0   r   r   r   isatty   s    z
Tee.isattyN)r   
__module____qualname__r2   r3   r8   r9   r:   r   r   r   r   r-   y   s
   r-   c                   s   e Zd ZdZdZdZdZdZ fddZdd	 Z	d
d Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd*d$d%Zd+d&d'Zd,d(d)Z  ZS )-XunitzCThis plugin provides test results in the standard XUnit XML format.Zxuniti  zUTF-8Nc                s$   t t|   g | _d | _d | _d S )N)superr=   r2   _capture_stack_currentStdout_currentStderr)r0   )r   r   r   r2      s    zXunit.__init__c             C   s    t | drt | j }nd}|S )N_timerg        )hasattrr   rB   )r0   takenr   r   r   
_timeTaken   s    
zXunit._timeTakenc             C   s   t |}t|S )z.Escape an XML attribute. Value can be unicode.)r   r   Z	quoteattr)r0   attrr   r   r   
_quoteattr   s    zXunit._quoteattrc          	   C   sN   t | || |jdddd|dddd |jd	dd
d|dddd dS )z%Sets additional command line options.z--xunit-fileZstore
xunit_fileZFILEZNOSE_XUNIT_FILEznosetests.xmlzrPath to xml file to store the xunit report in. Default is nosetests.xml in the working directory [NOSE_XUNIT_FILE])actiondestmetavardefaulthelpz--xunit-testsuite-namexunit_testsuite_nameZPACKAGEZNOSE_XUNIT_TESTSUITE_NAMEZ	nosetestszbName of the testsuite in the xunit xml, generated by plugin. Default test suite name is nosetests.N)r   optionsZ
add_optionget)r0   parserenvr   r   r   rO      s    

zXunit.optionsc             C   sL   t | || || _| jrHddddd| _g | _tj|j	| _
|j| _dS )zConfigures the xunit plugin.r   )errorsfailurespassesskippedN)r   	configureconfigZenabledstats	errorlistospathrealpathrH   error_report_file_namerN   )r0   rO   rX   r   r   r   rW      s    
zXunit.configurec                s   t  jd jd _ j jd<  j jd<  jd  jd   jd   jd   jd	<  jd
 j   jd fdd j	D   jd  j
   jjdkr|d |d jj  dS )zmWrites an Xunit-formatted XML file

        The file includes a report of test errors and failures.

        wr   r1   Ztestsuite_namerS   rT   rU   rV   Ztotalz<?xml version="1.0" encoding="%(encoding)s"?><testsuite name="%(testsuite_name)s" tests="%(total)d" errors="%(errors)d" failures="%(failures)d" skip="%(skipped)d"> c                s   g | ]}t | jqS r   )r   r1   ).0e)r0   r   r   
<listcomp>   s   z Xunit.report.<locals>.<listcomp>z</testsuite>r   zF----------------------------------------------------------------------zXML: %sN)codecsopenr^   r1   error_report_filerY   rN   r3   joinrZ   closerX   	verbosityZwritelnr   )r0   streamr   )r0   r   report   s    
.


zXunit.reportc             C   sP   | j tjtjf t | _t | _t| j	| jtjt_t| j	| jtjt_d S )N)
r?   appendsysstdoutstderrr   r@   rA   r-   r1   )r0   r   r   r   _startCapture   s
    zXunit._startCapturec             C   s   |    d S )N)rp   )r0   contextr   r   r   startContext   s    zXunit.startContextc             C   s   |    d S )N)_endCapture)r0   rq   r   r   r   stopContext   s    zXunit.stopContextc             C   s   t  | _|   dS )z+Initializes a timer before starting a test.N)r   rB   rp   )r0   testr   r   r   
beforeTest   s    zXunit.beforeTestc             C   s   | j r| j  \t_t_d S )N)r?   poprm   rn   ro   )r0   r   r   r   rs      s    zXunit._endCapturec             C   s   |    d | _d | _d S )N)rs   r@   rA   )r0   ru   r   r   r   	afterTest   s    zXunit.afterTestc             C   s   x| j r|   qW d S )N)r?   rs   )r0   ru   r   r   r   finalize   s    zXunit.finalizec             C   s$   | j r | j  }|r dt| S dS )Nz'<system-out><![CDATA[%s]]></system-out>r`   )r@   getvaluer   )r0   r   r   r   r   _getCapturedStdout  s    
zXunit._getCapturedStdoutc             C   s$   | j r | j  }|r dt| S dS )Nz'<system-err><![CDATA[%s]]></system-err>r`   )rA   rz   r   )r0   r   r   r   r   _getCapturedStderr  s    
zXunit._getCapturedStderrc             C   s   |   }t|d tr.d}| jd  d7  < nd}| jd  d7  < t|| j}| }| jd| 	t
|d | 	t
|d ||| 	t|d | 	t|t||  |  d	  d	S )
z*Add error output to Xunit report.
        r   rV   r   errorrS   z<testcase classname=%(cls)s name=%(name)s time="%(taken).3f"><%(type)s type=%(errtype)s message=%(message)s><![CDATA[%(tb)s]]></%(type)s>%(systemout)s%(systemerr)s</testcase>)	clsr   rD   typeerrtypemessagetb	systemout	systemerrN)rE   
issubclassr   rY   r   r1   idrZ   rl   rG   r   r$   r,   r   r{   r|   )r0   ru   errcaptrD   r   r   r   r   r   r   addError  s&    zXunit.addErrorc             C   s   |   }t|| j}| jd  d7  < | }| jd| t|d | t|d || t	|d | t
|t||  |  d  dS )z,Add failure output to Xunit report.
        rT   r   z<testcase classname=%(cls)s name=%(name)s time="%(taken).3f"><failure type=%(errtype)s message=%(message)s><![CDATA[%(tb)s]]></failure>%(systemout)s%(systemerr)s</testcase>r   r~   )r   r   rD   r   r   r   r   r   N)rE   r   r1   rY   r   rZ   rl   rG   r   r$   r,   r   r{   r|   )r0   ru   r   r   Ztb_inforD   r   r   r   r   r   
addFailure1  s    zXunit.addFailurec          	   C   sf   |   }| jd  d7  < | }| jd| t|d | t|d ||  |  d  dS )z,Add success output to Xunit report.
        rU   r   zb<testcase classname=%(cls)s name=%(name)s time="%(taken).3f">%(systemout)s%(systemerr)s</testcase>r   r~   )r   r   rD   r   r   N)	rE   rY   r   rZ   rl   rG   r   r{   r|   )r0   ru   r   rD   r   r   r   r   
addSuccessG  s    zXunit.addSuccess)N)NN)N)r   r;   r<   __doc__r   Zscorer1   rf   r2   rE   rG   rO   rW   rk   rp   rr   rt   rv   rs   rx   ry   r{   r|   r   r   r   __classcell__r   r   )r   r   r=      s.   


r=   )r   rd   Zdoctestr[   rm   	tracebackrer   ior   r   Zxml.saxr   Znose.plugins.baser   Znose.excr   Znose.pyversionr   r   compiler
   r   r   r   r   r$   r,   objectr-   r=   r   r   r   r   <module>)   s,   

	