Я писал токенизатор для небольшого языка, который я разрабатываю в свободное время, и я хочу протестировать его с отрицательным вводом. Мой код может вызывать два вида Exception
s, IndentationError
и SyntaxError
, и это выглядит примерно так:
class Tokenizer:
def __init__(self, source:str) -> None:
self.source = source
...
def get_next_token(self) -> Token:
"""Returns the next token and advances the position pointer into self.source"""
...
def tokenize(self) -> Generator[Token, None, None]:
"""Calls get_next_token until all of self.source has been scanned"
...
Затем в тестах у меня есть списки со всеми видами ввода , Например:
SYNTAX_ERROR_SOURCES = ["(}", "[}", "{]", "a@b"] # Note that @ is not a supported operand
И тогда одна из тестовых функций выглядит следующим образом:
@pytest.mark.parametrize("source", SYNTAX_ERROR_SOURCES)
def test_tokenize_fail_syntax_error(source: str) -> None:
with pytest.raises(SyntaxError):
Tokenizer(source).tokenize()
Проблема в том, что tokenize
никогда не вызывается внутри диспетчера контекста, и я не уверен почему. Я могу подтвердить это, запустив код под отладчиком. Когда он достигает линии, где вызывается tokenize
, он напрямую переходит к некоторому коду pytest
, и после этого тест завершается неудачно с Failed: DID NOT RAISE <class 'SyntaxError'>
, даже не входя в tokenize
.
Кроме того, если я выполните tokenizer.py как скрипт с python tokenizer.py "a@b"
, тогда все в порядке, и программа завершается с SyntaxError, как и ожидалось.
Кто-нибудь когда-нибудь сталкивался с чем-то подобным?