2017-12-01 4 views
1

역 추적하는 방법을 :pytest 사용자 정의 주장, 나는이 같은 간단한 테스트 코드를 가지고

test_assert.py

import helper 


def test_assert(): 
    assert helper.find_event(helper.HelperEvents("event","this is info")) is True 

이 helper.py

helper_list = [] 


class HelperEvents: 
    def __init__(self, event, info): 
     self.event = event 
     self.info = info 


def add_event(event): 
    helper_list.append(event) 


def find_event(event): 
    try: 
     helper_list.index(event, 0, 100) 
    except ValueError: 
     return False 
    return True 

이 나에게 AssertionError를 줄 것이다 like :

def test_assert(): 
>  assert helper.find_event(helper.HelperEvents("event","this is info")) is True 
E  AssertionError: assert False is True 
E  + where False = <function find_event at 0x158c9b0>(<test_asserts.helper.HelperEvents instance at 0x157d488>) 
E  + where <function find_event at 0x158c9b0> = helper.find_event 
E  + and <test_asserts.helper.HelperEvents instance at 0x157d488> = <class test_asserts.helper.HelperEvents at 0x1670188>('event', 'this is info') 
E  +  where <class test_asserts.helper.HelperEvents at 0x1670188> = helper.HelperEvents 

test_assert.py:5: AssertionError 

난 정말이 같은 해당를 단순화 할 : 않고 ​​AssertionError를 이벤트 : 이벤트 정보 :이 정보는

이렇게하려면, 나는 초기화 평 파일을 만든 목록에서 찾을 수 없습니다입니다

import pytest 
pytest.register_assert_rewrite('test_asserts') 

과 conftest.py 파일 :

import pytest 


@pytest.hookimpl(tryfirst=True) 
def pytest_assertrepr_compare(op, left, right): 
    print "Left:", left 
    print "op:", op 
    print "Right:", right 
    return [str(left), op, str(right)] 

다음 나에게 제공합니다

def test_assert(): 
>  assert helper.find_event(helper.HelperEvents("event","this is info")) is True 
E  assert False 
E   is 
E   True 

test_assert.py:5: AssertionError 

find_event 호출의 결과 만 제공되는 경우 어떻게 이벤트에서 정보를 추출합니까?

답변

0

그래서 pytest_runtest_makereport에 대한 후크를 구현했습니다. pytests 구현에서 코드를 재사용하고이를 내 자신의 사용자 정의 어설 션 표현으로 확장했습니다. 은 다음과 같습니다

import pytest 
from _pytest._code.code import ExceptionInfo 
from _pytest.outcomes import skip 
from _pytest._code.code import ReprTraceback, ReprEntry, ReprFileLocation, Traceback 
from _pytest.runner import TestReport 


@pytest.hookimpl(tryfirst=True) 
def pytest_runtest_makereport(item, call): 
    when = call.when 
    duration = call.stop - call.start 
    keywords = dict([(x, 1) for x in item.keywords]) 
    excinfo = call.excinfo 
    sections = [] 
    if not call.excinfo: 
     outcome = "passed" 
     longrepr = None 
    else: 
     if not isinstance(excinfo, ExceptionInfo): 
      outcome = "failed" 
      longrepr = excinfo 
     elif excinfo.errisinstance(skip.Exception): 
      outcome = "skipped" 
      r = excinfo._getreprcrash() 
      longrepr = (str(r.path), r.lineno, r.message) 
     else: 
      outcome = "failed" 
      if call.when == "call": 
       longrepr = custom_excinfo_repr(excinfo) # This creates my custom assert representation 
      else: # exception in setup or teardown 
       longrepr = item._repr_failure_py(excinfo, 
               style=item.config.option.tbstyle) 
    for rwhen, key, content in item._report_sections: 
     sections.append(("Captured %s %s" % (key, rwhen), content)) 
    if longr 


def beautify_exc_output(lines): 
    out = [] 
    if any("helper.find_event" in s for s in lines): 
     out = parseAssert(lines) 
    return out 


def parseAssertion(lines): 
    assertionType = "" 
    args = [] 
    out = [] 
    compare = [] 

    # extract data from input 
    for line in lines: 
     line = line.strip("+ ") 
     if "AssertionError" in line: 
      assertionType = line[line.find("assert"):] 
      compare = [int(s) for s in assertionType.split() if s.isdigit()] # Check if assertion was an integer compare 
     if "HelperEvents" in line and "where" not in line: 
      content = line[line.find("(")+1:line.find(")")] # Find content of event 
      args = [x.strip(" '") for x in content.split(",")] # split in to args 

    # Generate output 
    if len(args) > 1 and len(assertionType) > 0: 
     Indent = " " 
     out.append("Assertion error in HelperEvents:") 
     out.append("###############################################################") 
     if len(compare) == 2: 
      out.append(" Expected {0} times {1} but got {2} times".format(compare[1], args[0], compare[0])) 
     out.append(" " + GetAssertionEvent(assertionType)) 
     out.append(Indent + "Event: {}".format(args[0])) 
     out.append(Indent + "Info: {}".format(args[1])) 
     out.append("###############################################################") 
    return out 


def GetAssertionEvent(AssertionType): 
    if "assert not False" in AssertionType or \ 
      "assert True is False" in AssertionType or \ 
      "assert True" in AssertionType: 
     return "Unexpected event has been received" 
    elif "assert False" in AssertionType or \ 
      "assert False is True" in AssertionType: 
     return "Expected event was not received" 
    else: 
     return AssertionType 

이 모든 코드는 지금 conftest.py에 배치됩니다. 어설 션이 구현에 의해 인식되지 않는 유형 인 경우, 내 후크에서 없음을 반환하므로 pytest가 기본 구현을 사용합니다.