'''The tests for all CSC 3340 project problems, as well as the solution to the problem. Author: Kyle Burke <kwburke@plymouth.edu>''' import math import sys import pymongo import datetime import copy project_number = 6 def test_part(func, context, message_list): '''Runs f, a function with the elements of context (followed by message_list) as it's parameters that tests the part. If f completes, then the test succeeds, and this returns True. If f throws an exception, then it prints the string at message_list[0] and returns False. f should be written so that it stores the relevant error message in message_list[0] before any statement that could cause an exception.''' #print("Called test_part...") try: func(*context, message_list) #print("Finished calling func!") except Exception as e: print(e) return False return True def assert_true(test): if not test: raise Exception() def assert_false(test): if test: raise Exception() def sub_record(key, result): for entry in key: if not entry in result: return False return True ############### Tests!!!!!!! ########################### ### Table Setup tests ### print("Starting the grading!") print("IMPORTANT: This does not include all of my tests! Your score might be lower than what you get here if you don't test all other things carefully. For most parts, my tests are more comprehensive. The best thing you can do is to add more tests. (If you do that, do not share with other groups if it includes solutions.) You can still upload your code and ask me to review it.") students = [] students.append(input("Please enter your teamname: ")) feedbacks = [] for student in students: feedback_text = "" score = 0 connection = pymongo.MongoClient() #Import the student file and call their main function if they have one stu_module = __import__(student + "_project" + str(project_number)) if hasattr(stu_module, "main"): stu_module.main() stu_db = connection[student] parts = [] #part 0: all royals def part_0_test(stu_db, error_list): #check whether the collection exists error_list[0] = "No collection named 'british-royals'." stu_collection = stu_db['british-royals'] expected_names = ["Elizabeth", "James Charles Stuart", ("Charles", 2)] for name in expected_names: expected_num_docs = 1 if isinstance(name[1], int): expected_num_docs = name[1] name = name[0] cursor = stu_collection.find({"full name" : name}) results = list(cursor) num_results = len(results) error_list[0] = "Didn't find any documents for the full name " + name assert_true(num_results > 0) error_list[0] = "Didn't find the correct number of documents for the name " + name assert_true(num_results == expected_num_docs) parentages = [("George Frederick Ernest Albert", "Edward Albert Christian George Andrew Patrick David"), ("Albert Edward", "George Frederick Ernest Albert")] for (parent_name, child_name) in parentages: error_list[0] = "Couldn't get one of the royals from the collection: " + child_name child = stu_collection.find_one({"full name" : child_name}) assert_true(child != None) error_list[0] = "Couldn't get one of the royals from the collection: " + parent_name parent = stu_collection.find_one({"full name" : parent_name}) assert_true(parent != None) error_list[0] = child_name + " doesn't have a parents field" parent_id = parent["_id"] parent_ids = child['parents'] error_list[0] = child_name + " is missing at least one parent (or has them incorrectly recorded)." assert_true(parent_id in parent_ids) parts.append((part_0_test, [stu_db], 25)) def part_1_test(stu_db, error_list): #check whether the collection exists error_list[0] = "No collection named 'british-royals'." stu_collection = stu_db['british-royals'] regnal_names = ["Elizabeth", "James"] for regnal_name in regnal_names: error_list[0] = "Got an exception while looking for the regnal name " + regnal_name results = list(stu_collection.find({"name" : regnal_name})) error_list[0] = "Failed to find a document for the regnal name " + regnal_name assert_true(len(results) > 0) error_list[0] = "Got multiple documents matching the regnal name " + regnal_name assert_true(len(results) == 1) parts.append((part_1_test, [stu_db], 20)) #tests get_regnal_name def part_2_test(stu_db, stu_module, error_list): #check whether the collection exists error_list[0] = "No collection named 'british-royals'." stu_collection = stu_db['british-royals'] regnal_name_pairs = [ ["Elizabeth", [ "Elizabeth", "Elizabeth Alexandra Mary"]], ["James", [ "James Charles Stuart", "James"]]] for (regnal_name, full_names) in regnal_name_pairs: for full_name in full_names: error_list[0] = "Threw an exception while calling the function on " + full_name result = stu_module.get_regnal_name(stu_collection, full_name) error_list[0] = "Incorrect regnal name for " + full_name assert_true(result == regnal_name) parts.append((part_2_test, [stu_db, stu_module], 10)) #tests get_monarchs_by_name def part_3_test(stu_db, stu_module, error_list): #check whether the collection exists error_list[0] = "No collection named 'british-royals'." stu_collection = stu_db['british-royals'] regnal_name_pairs = [ ["Elizabeth", [ "Elizabeth", "Elizabeth Alexandra Mary"]], ["James", [ "James Charles Stuart", "James"]]] for (regnal_name, full_names) in regnal_name_pairs: error_list[0] = "Threw an exception while calling the function on " + regnal_name result = stu_module.get_monarchs_by_name(stu_collection, regnal_name) error_list[0] = "Didn't return a list for " + regnal_name assert_true(isinstance(result, list)) error_list[0] = "Incorrect monarchs for " + regnal_name assert_true(set(result) == set(full_names)) parts.append((part_3_test, [stu_db, stu_module], 10)) #tests get_reign_range def part_4_test(stu_db, stu_module, error_list): #check whether the collection exists error_list[0] = "No collection named 'british-royals'." stu_collection = stu_db['british-royals'] reign_range_pairs = [ ("Queen Elizabeth I", (1558, 1603)), ("King James I", (1603, 1625)), ("King Marshmallow I", None)] for (royal_name, reign_range) in reign_range_pairs: error_list[0] = "Threw an exception while calling the function on " + royal_name result = stu_module.get_reign_range(stu_collection, royal_name) if reign_range == None: error_list[0] = "Didn't return None for a royal name that didn't reign: " + royal_name assert_true(result == None) else: error_list[0] = "Didn't return a 2-tuple for " + royal_name assert_true(isinstance(result, tuple)) assert_true(len(result) == 2) error_list[0] = "Didn't return a tuple of ints for " + royal_name assert_true(isinstance(result[0], int)) assert_true(isinstance(result[1], int)) error_list[0] = "Incorrect years for " + royal_name assert_true(result == reign_range) parts.append((part_4_test, [stu_db, stu_module], 10)) #tests get_reign_lengths_by_length def part_5_test(stu_db, stu_module, error_list): #check whether the collection exists error_list[0] = "No collection named 'british-royals'." stu_collection = stu_db['british-royals'] current_year = datetime.datetime.now().year actual_lengths = [0, 3, 5] charles_3_reign = current_year - 2022 actual_lengths.append(charles_3_reign) actual_lengths.sort() error_list[0] = "Threw an exception while calling the function." stu_lengths = stu_module.get_reign_lengths_by_length(stu_collection) error_list[0] = "Doesn't return a list." assert_true(isinstance(stu_lengths, list)) error_list[0] = "Returns the wrong list." assert_true(stu_lengths[ : len(actual_lengths)] == actual_lengths) parts.append((part_5_test, [stu_db, stu_module], 10)) #tests get_reign_lengths_by_length def part_6_test(stu_db, stu_module, error_list): #check whether the collection exists error_list[0] = "No collection named 'british-royals'." stu_collection = stu_db['british-royals'] actual_name_possibilities = [ ['Queen Elizabeth II', 'Queen Victoria', 'King George III']] error_list[0] = "Threw an exception while calling the function." result = stu_module.get_royal_names_by_reign_lengths(stu_collection) error_list[0] = "Doesn't return a list." assert_true(isinstance(result, list)) error_list[0] = "Returns the wrong list." assert_true(result[ : len(actual_name_possibilities[0])] in actual_name_possibilities) parts.append((part_6_test, [stu_db, stu_module], 10)) #tests get_regnal_name_length def part_7_test(stu_db, stu_module, error_list): current_year = datetime.datetime.now().year charles_3_reign = current_year - 2022 #check whether the collection exists error_list[0] = "No collection named 'british-royals'." stu_collection = stu_db['british-royals'] reign_length_pairs = [ ("Elizabeth", 115), ("Charles", 49 + charles_3_reign), ("Monkey", 0)] for (regnal_name, reign_length) in reign_length_pairs: error_list[0] = "Threw an exception while calling the function on " + regnal_name result = stu_module.get_regnal_name_length(stu_collection, regnal_name) error_list[0] = "Doesn't return an int for " + regnal_name assert_true(isinstance(result, int)) error_list[0] = "Doesn't return the right result for " + regnal_name parts.append((part_7_test, [stu_db, stu_module], 5)) #TODO: this should probably be encapsulated into a function. for i in range(len(parts)): part_tuple = parts[i] part_test = part_tuple[0] context = part_tuple[1] max_points = part_tuple[2] error_list = ["Blank"] #print("Calling test_part...") correct = test_part(part_test, context, error_list) if correct: part_points = max_points error_message = "" else: part_points = 0 error_message = "\n " + error_list[0] feedback_text += "Part " + str(i) + ": " + str(part_points) + "/" + str(max_points) + error_message + "\n" feedback_text += "\n" score += part_points print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") print() print("Team " + student + ": " + str(score) + "/100\n\n" + feedback_text) print() stu_collection = stu_db['british-royals']