Pytest for ex49


#1

Hello.

After a long time I have put my self together and finished ex49.
I have uploaded to Github.
I also put it in here to read and comment.
At last I managed to figure out how to make simple fixtures (there is a lot of advanced examples if you Google).
I think this test cover most of parser.py.
[edit]
I have found out how to write the tests for the error messages.
See update below.

Please feel free to make comments or suggestion on how to improve.
I also hope that it can be useful for for other who want to use Pytest.


from ex48 import parser, lexicon
from ex48.parser import *
import pytest

@pytest.fixture
def wordlist_fix():
    return lexicon.scan('the princess kill bear')

# Not needed anymore.
# @pytest.fixture
# def wordlist_error_fix():
#    return lexicon.scan('the bear princess kill') # Sentence with Yoda 'grammar' 

# This fixture replaces fixture above:
@pytest.fixture
def parse_error_msg():
    return lexicon.scan('the the the the') # All the "the" is for NOT match verb, noun or direction


def test_Sentence():
    a = Sentence(('noun','princess'), ('verb', 'kill'), ('noun', 'bear'))
    assert a.subject == 'princess'
    assert a.verb == 'kill'
    assert a.object == 'bear'

def test_peek(wordlist_fix):
    assert parser.peek(wordlist_fix) ==  'stop'  

def test_peek_empty():
    wordlist = []
    assert parser.peek(wordlist) == None

def test_match(wordlist_fix):
    w = wordlist_fix.pop(0)
    assert w == ('stop','the') # Popped off from wordlist_fix
    x = wordlist_fix
    assert x == [('noun', 'princess'),('verb', 'kill'), ('noun', 'bear')]
    # Remainder of wordlist_fix

def test_skip(wordlist_fix):
    assert peek(wordlist_fix) == 'stop'

def test_parse_verb(wordlist_fix):
    skip(wordlist_fix, 'stop')
    match(wordlist_fix, 'expecting') 
    # "expecting" can be replaced with anything to make peek(wordlist_fix) equal to 'verb'
    # otherwise it only equals 'noun'.  (correct ?) 
    assert peek(wordlist_fix) == 'verb'

def test_object(wordlist_fix):
    skip(wordlist_fix, 'stop')
    next_word = peek(wordlist_fix)
    assert next_word == 'noun'

def test_subject(wordlist_fix):
    skip(wordlist_fix, 'stop')
    next_word = peek(wordlist_fix)
    assert next_word == 'noun'
    skip(wordlist_fix, 'verb')
    next_word = peek(wordlist_fix)
    assert next_word == 'noun'

def test_parse_sentence(wordlist_fix):
    subj = parse_subject(wordlist_fix)
    verb = parse_verb(wordlist_fix)
    obj = parse_object(wordlist_fix)
    assert subj == ('noun', 'princess')
    assert verb == ('verb', 'kill')
    assert obj == ('noun', 'bear')

def test_error_message():
    with pytest.raises(ParserError) as excinfo:
         parse_sentence([('noun', 'princess'),('bear', 'kill'), ('a', 'error')])
    assert str(excinfo.value) == 'Expected a verb next.'

def test_error_message2(wordlist_error_fix):
    with pytest.raises(ParserError) as excinfo:
        parse_sentence(wordlist_error_fix)
assert str(excinfo.value) == 'Expected a verb next.'

Did some work on the error messages.
I have changed the last test functions in previous code (above) with the three following functions (below).

def test_error_message_parse_verb(parse_error_msg):
    with pytest.raises(ParserError) as excinfo:
        parse_verb(parse_error_msg)
    assert str(excinfo.value) == 'Expected a verb next.'

def test_error_message_parse_subject(parse_error_msg):
    with pytest.raises(ParserError) as excinfo:
        parse_subject(parse_error_msg)
    assert str(excinfo.value) == 'Expected a verb next.'

def test_error_message_parse_object(parse_error_msg):
    with pytest.raises(ParserError) as excinfo:
        parse_object(parse_error_msg)
    assert str(excinfo.value) == 'Expected a noun or direction next.'

The fixture: wordlist_error_fix is not needed anymore.

Opps. Almost forgot.
This fixture is needed instead:

@pytest.fixture
def parse_error_msg():
    return lexicon.scan('the the the the') 
# All the "the" is for NOT match verb, noun or direction

#2

Hey, that actually looks pretty good. Iā€™m happy with it.