# coding=utf-8
"""
Aaron Buchanan
Nov. 2012

Plug-in for py.test for reporting to TeamCity server
Report results to TeamCity during test execution for immediate reporting
    when using TeamCity.

This should be installed as a py.test plugin and is enabled by running
py.test with a --teamcity command line option.
"""

import py
import os
from datetime import timedelta

from teamcity.messages import TeamcityServiceMessages


def pytest_addoption(parser):
    group = parser.getgroup("terminal reporting", "reporting", after="general")
    group._addoption('--teamcity', action="count",
                     dest="teamcity", default=0, help="output teamcity messages")


def pytest_configure(config):
    if config.option.teamcity >= 1:
        config._teamcityReporting = EchoTeamCityMessages()
        config.pluginmanager.register(config._teamcityReporting)


def pytest_unconfigure(config):
    teamcity_reporting = getattr(config, '_teamcityReporting', None)
    if teamcity_reporting:
        del config._teamcityReporting
        config.pluginmanager.unregister(teamcity_reporting)


class EchoTeamCityMessages(object):
    def __init__(self, ):
        self.tw = py.io.TerminalWriter(py.std.sys.stdout)
        self.teamcity = TeamcityServiceMessages(self.tw)
        self.currentSuite = None

    def format_names(self, name):
        file, testname = name.split("::", 1)
        if not testname:
            testname = file
            file = 'NO_TEST_FILE_FOUND'
        testname = testname.replace("::()::", ".")
        testname = testname.replace("::", ".")
        testname = testname.strip(".")
        file = file.replace(".", "_").replace(os.sep, ".").replace("/", ".")
        return file, testname

    def pytest_runtest_logstart(self, nodeid, location):
        file, testname = self.format_names(nodeid)
        if not file == self.currentSuite:
            if self.currentSuite:
                self.teamcity.testSuiteFinished(self.currentSuite)
            self.currentSuite = file
            self.teamcity.testSuiteStarted(self.currentSuite)
        self.teamcity.testStarted(testname)

    def pytest_runtest_logreport(self, report):
        file, testname = self.format_names(report.nodeid)
        if report.passed:
            if report.when == "call":  # ignore setup/teardown
                duration = timedelta(seconds=report.duration)
                self.teamcity.testFinished(testname, testDuration=duration)
        elif report.failed:
            if report.when == "call":
                self.teamcity.testFailed(testname, str(report.location), str(report.longrepr))
                duration = timedelta(seconds=report.duration)
                self.teamcity.testFinished(testname, testDuration=duration)  # report finished after the failure
        elif report.skipped:
            self.teamcity.testIgnored(testname, str(report.longrepr))
            self.teamcity.testFinished(testname)  # report finished after the skip

    def pytest_sessionfinish(self, session, exitstatus, __multicall__):
        if self.currentSuite:
            self.teamcity.testSuiteFinished(self.currentSuite)

@@ -2497,25 +2497,36 @@
 rt.when 
-== 
+in (
 %22call%22
+, %22setup%22)
 :%0A      
@@ -2668,32 +2668,32 @@
 eport.duration)%0A
-
                 
@@ -2789,16 +2789,294 @@
 failure%0A
+            elif report.when == %22teardown%22:%0A                name = testname + %22_teardown%22%0A                self.teamcity.testStarted(name)%0A                self.teamcity.testFailed(name, str(report.location), str(report.longrepr))%0A                self.teamcity.testFinished(name)%0A
         

Support reporting of setup and teardown failures (marked as errors in py.test), relates to #14