pythonpytest
Ben Gorman

Ben Gorman

Life's a garden. Dig it.

You're developing a knock-off Scrabble game. You've implemented a Scrabble class that initializes with a specific list of characters, ['s', 'a', 'r', 'b', 'k', 'r', 'e']. It has a play_word(self, word: str) method that doesn't do anything, but it does throw an error if the word you try to play can't be formed from the list of letters.

For example,

  1. Instantiate a new Scrabble game

    scrabble = Scrabble()
    print(scrabble.letters)  # ['s', 'a', 'r', 'b', 'k', 'r', 'e']
  2. Play a valid word

    scrabble.play_word('bark')  # returns None
  3. Play an invalid word

    scrabble.play_word('meatloaf')
    # ScrabbleWordException: You can't form the word 'meatloaf' with the letters ['s', 'a', 'r', 'b', 'k', 'r', 'e']

Write a test to confirm that playing an invalid word raises the correct ScrabbleWordException.

Directory Structure

scrabble/
  scrabble.py
  test_scrabble.py

Files

class ScrabbleWordException(Exception):
    """Custom Scrabble Exception"""
    pass
 
class Scrabble():
    """
    Fake Scrabble, where the tiles don't have points,
    there's no wildcard tiles, and your letters are
    pre-selected
    """
 
    def __init__(self):
        self.letters = ['s', 'a', 'r', 'b', 'k', 'r', 'e']
 
    def play_word(self, word: str):
        """
        Play a word
 
        should be any string formed from the characters in self.letters
 
        :param word: a string formed from the letters in self.letters
        :return: True if word can be formed from self.letters
        """
 
        letters = self.letters.copy()
        for char in word:
            try:
                letters.remove(char)
            except ValueError as e:
                raise ScrabbleWordException(f"You can't form the word '{word}' with the letters {self.letters}")
def test_invalid_word():
    """
    If the user plays an invalid word,
    make sure the right exception is raised.
    """
    
    # your code here

Solution

test_scrabble.py
import pytest
from scrabble import ScrabbleWordException, Scrabble
 
def test_invalid_word():
    """
    If the user plays an invalid word,
    make sure the right exception is raised.
    """
 
    scrabble = Scrabble()
 
    # First make sure the letters are what we expect
    assert(scrabble.letters == ['s', 'a', 'r', 'b', 'k', 'r', 'e'])
 
    # Confirm that ScrabbleWordException is raised with the right message
    with pytest.raises(ScrabbleWordException, match=r"can't form the word 'meatloaf'") as e_info:
        scrabble.play_word('meatloaf')

Explanation

  1. First we need to import pytest and scrabble stuff.

    import pytest
    from scrabble import ScrabbleWordException, Scrabble
  2. Instantiate a new Scrabble instance.

    scrabble = Scrabble()
  3. Make sure the preset letters are what we believe them to be!

    # First make sure the letters are what we expect
    assert(scrabble.letters == ['s', 'a', 'r', 'b', 'k', 'r', 'e'])
  4. Use pytest.raises() to confirm that scrabble.play_word('meatloaf') generates a ScrabbleWordException with an error message like "can't form the word 'meatloaf'".

    # Confirm that ScrabbleWordException is raised with the right message
    with pytest.raises(ScrabbleWordException, match=r"can't form the word 'meatloaf'") as e_info:
        scrabble.play_word('meatloaf')