Permalink
Browse files

userInterface.py now takes a question object as a parameter and not a…

… quiz object. The test code in userInterfaceUnitTest.py has been modified to reflect the change.
  • Loading branch information...
1 parent c229e15 commit ddd7a3826f9a55401eefe920d764710f55661848 @humphriesaj humphriesaj committed Sep 23, 2012
Showing with 261 additions and 0 deletions.
  1. +96 −0 userInterface.py
  2. +165 −0 userInterfaceUnitTest.py
View
@@ -0,0 +1,96 @@
+#!/usr/bin/python3.1
+
+__author__ = "Tony Humphries"
+__date__ = "09/17/12"
+
+import string
+
+class UserInterface:
+ """Class which provides the interface for a user to answer quiz
+ questions. The object provides methods for displaying the question and
+ possible answers as well as displaying whether the answer given was
+ correct or incorrect. Special dependencies include ..."""
+
+ def __init__(self, Question):
+ # Set _questionObj to the question object passed in.
+ self._questionObj = Question
+ # This is an index of the alphabet when set.
+ self._userAnswer = None
+ self._alphabet = string.ascii_lowercase
+
+ def _formatChoice(self, choiceIndex, choiceText):
+ """Returns a string with the appropriate letter and formatting
+ before the choice passed to the function. It should be noted
+ that for a given question, the number of choices cannot exceed
+ 26, since this is the number of lettersin the English
+ alphabet."""
+ return self._alphabet[choiceIndex]+".)\t"+choiceText
+
+ def _updateQuestion(self, newQuestion):
+ """Updates self._questionObj to be the next question object
+ from the quiz. This new question is passed as a parameter
+ which is a question object."""
+ self._questionObj = newQuestion
+ # This is to prevent the same answer from being submitted
+ # without the user specifying so.
+ self._userAnswer = None
+
+ def updateQuestion(self, newQuestion):
+ self._updateQuestion(newQuestion)
+
+ def welcome(self):
+ """Welcomes the user to the quiz."""
+ print("Welcome to your quiz. Press Enter to continue.\n")
+ input()
+
+ def displayQuestion(self):
+ """Prints the question and possible answers on the screen."""
+ # questionText is a string containing the question to
+ # be displayed.
+ questionText = self._questionObj.getQuestionText()
+ # choices is a tuple of the possible answers to be
+ # displayed in the order they will be displayed on
+ # the screen.
+ choices = self._questionObj.getChoices()
+ # Display the question.
+ print(questionText, '\n')
+ # Display the choices.
+ for i, choice in enumerate(choices):
+ print(self._formatChoice(i, choice))
+
+ def endOfQuiz(self):
+ """Prints a message indicating the user has completed the quiz
+ when called."""
+ print("\nYou have completed the quiz.")
+
+ def prompt(self):
+ """Prompts the user for input on the given question and set
+ _userAnswer to the letter of their choice. Given that the user
+ enters a letter that is not given as a choice, they will be
+ prompted again until that letter is chosen. The user may enter
+ either the lowercase or the uppercase form of the letter with
+ leading and/or trailing whitespace."""
+ answer = ""
+ numOfChoices = len(self._questionObj.getChoices())
+ # Check the answer's length, whether or not it's in the
+ # alphabet, and whether or not it's index in the alphabet is
+ # in the range of choices.
+ while len(answer) != 1 or answer not in self._alphabet or \
+ self._alphabet.index(answer) \
+ not in range(numOfChoices):
+
+ answer = input("\n:> ")
+ answer = answer.lower()
+ answer = answer.strip()
+ # Get the index position of the letter for the final answer.
+ self._userAnswer = self._alphabet.index(answer)
+
+ def getResponse(self):
+ """Returns whether the user entered the correct answer or not.
+ Returns True if the answer was correct, and returns False if
+ the answer was incorrect."""
+ if self._userAnswer == self._questionObj.getAnswer():
+ return True
+ else:
+ return False
+
@@ -0,0 +1,165 @@
+#!/usr/bin/python3.1
+
+__author__ = "Tony Humphries"
+__date__ = "09/17/12"
+
+
+class Question:
+ """A dummy class used to return values for testing userInterface.py"""
+
+ def __init__(self, questionText, choices, answer):
+ self._questionText = questionText
+ self._choices = choices
+ self._answer = answer
+
+ def getQuestionText(self):
+ return self._questionText
+
+ def getChoices(self):
+ return self._choices
+
+ def getAnswer(self):
+ return self._answer
+
+class Quiz:
+ """A dummy Quiz object used for testing userInterface.py"""
+
+ def __init__(self):
+ # We're going to use this to iterate over different questions
+ # to test that the question of the interface gets updated
+ # properly. This is an indicator of which quesiton the quiz
+ # object is to fetch.
+ self._questionCount = -1
+
+ def getQuestion(self):
+ """Get the question."""
+ self._questionCount += 1
+ if self._questionCount < 3:
+ return Question(self._questionCount)
+ else:
+ # Return None when we're out of questions.
+ return None
+
+
+
+import unittest
+import userInterface
+import string
+
+def _makeQuestion(indx):
+ """This is used to make a new question to pass to the interface. The
+ code here does not reflect the functions behind creating new
+ questions. It is for testing only. The function gets the question
+ based on indices 0, 1, or 2."""
+
+ if indx == 0:
+ # The answer is at index 3 of the tuple of choices.
+ return Question("This is my dummy question. How are you?", \
+ ("Fine, thank you.", "Not well.", \
+ "Why are you asking?", "That's trash."), 3)
+ elif indx == 1:
+ # The answer is at index 2
+ return Question("How much is a diet coke in the Student Lounge in the Olin building at Wofford?", \
+ ("$1.75", "$1.00", "$1.35", "$1.50", "$1.25"), 2)
+ elif indx == 2:
+ # The answer is at index 0
+ return Question("What is the name of the supercomputer that two Wofford students who graduated in the past two years work on today?", \
+ ("Kraken", "Sequoia", "Jaguar"), 0)
+# This is only used for testing
+indx = 0
+
+# Make the Question object.
+_questionObj = _makeQuestion(indx)
+# Make the interface object.
+_interfaceObj = userInterface.UserInterface(_questionObj)
+# My own alphabet string for testing.
+_alphabet = "abcdefghijklmnopqrstuvwxyz"
+
+def initTest():
+ """This test asserts that the interface has been initialized
+ properly."""
+ assert type(_interfaceObj._questionObj) == type(_makeQuestion(indx))
+ assert _interfaceObj._userAnswer == None
+ assert _interfaceObj._alphabet == _alphabet
+ print("initTest() ran successfully")
+
+def formatChoiceTest():
+ """This tests that _interfaceObj._formatChoice() formats a line
+ for a choice properly."""
+ # We'll iterate over all allowed input for the choiceIndex parameter.
+ for i in range(26):
+ try:
+ # Check that the first character is the correct letter
+ # for this choice.
+ assert _interfaceObj._formatChoice(i, "text")[0] \
+ == _alphabet[i]
+ # Check that the rest is right.
+ assert _interfaceObj._formatChoice(i, "text")[1:] \
+ == ".)\ttext"
+ except AssertionError:
+ print("Assertion error at index "+i+".")
+ raise
+ print("formatChoiceTest() ran successfully")
+
+def interfaceTest():
+ """Tests the interface as a whole. Do not rely on this test code to
+ confirm that the interface is visually appealing. That is up to the
+ tester."""
+ # Welcome the user.
+ _interfaceObj.welcome()
+ # Update the question.
+ _interfaceObj.updateQuestion(_makeQuestion(indx))
+ # Assert that there is a question object in the interface object's
+ # class variables.
+ assert type(_interfaceObj._questionObj) == \
+ type(_makeQuestion(indx))
+ # We have 3 test quesitons
+ for i in range(3):
+ _interfaceObj.displayQuestion()
+ _interfaceObj.prompt()
+ # Now there should be an answer in the appropriate class
+ # variable. Check that it is valid
+ assert _interfaceObj._userAnswer != None
+ numOfChoices = len(_interfaceObj._questionObj.getChoices())
+ assert _interfaceObj._userAnswer in range(numOfChoices)
+ # Check that _interfaceObj.getResponse() is working correctly.
+ # This is displayed as debugging output and should be ignored
+ # in regard to the appearance of the interface.
+ print("DEBUG_OUTPUT: getResponse() returned", \
+ _interfaceObj.getResponse(), \
+ "for your response.")
+ # Update the question for the next test. TODO: This needs to
+ # be changed.
+ # This is only for testing purposes.
+ global indx
+ indx += 1
+ _interfaceObj.updateQuestion(_makeQuestion(indx))
+ # Call the function indicating that the quiz is over.
+ _interfaceObj.endOfQuiz()
+ print("interfaceTest() ran successfully")
+
+def resetGlobals():
+ """Sets the global variables of this unit test to what they were
+ initialized to be."""
+ global _questionObj
+ global _interfaceObj
+ global indx
+ indx = 0
+ _questionObj = _makeQuestion(indx)
+ _interfaceObj = userInterface.UserInterface(_questionObj)
+ # The _alphabet variable should never have changed.
+
+def runAll():
+ """Run all tests in this module."""
+ initTest()
+ formatChoiceTest()
+ interfaceTest()
+ print("runAll() ran successfully")
+
+def main():
+ runAll()
+ resetGlobals()
+
+if __name__ == "__main__":
+ main()
+

0 comments on commit ddd7a38

Please sign in to comment.