def test_2_decode(self): print("------------------------------------\nTesting decode.") encoder = HuffmanEncoder("Where in the world is Carmen Sandiego?") encoder.do_setup() sequence_to_decode = [ 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0 ] self.assertEqual(encoder.decode_message(sequence_to_decode), "on the internet", "Decoded phrase does not match.")
def test_frequency_dict(self): encoder = HuffmanEncoder("The quick brown fox") encoder.build_frequency_dictionary() self.assertEqual(encoder.freq_dict["q"], 1, "\"q\" should be found once.") self.assertEqual(encoder.freq_dict["o"], 2, "\"o\" should be found twice.") self.assertEqual(encoder.freq_dict[" "], 3, "\" \" should be found three times.") self.assertFalse("j" in encoder.freq_dict, "\"j\" should not be found in the string.") self.assertTrue("x" in encoder.freq_dict, "\"x\" should be found in the string.") expected = {"T": 1, "h": 1, "e": 1, " ": 3, "q": 1, "u": 1, "i": 1, "c": 1, "k": 1, "b": 1, "r": 1, \ "o": 2, "w": 1, "n": 1, "f": 1, "x": 1} self.assertEqual(encoder.freq_dict, expected, "Did not get expected dictionary.") print(encoder.freq_dict)
def test_PQ_long(self): """ tests whether a frequency dictionary is created correctly with a longer piece of text. :param self: :return: """ #text from "Snow Crash" by Neal Stephenson, copyright 1992, [four-letter words slightly altered.] sample_text = """Chapter One The Deliverator belongs to an elite order, a hallowed subcategory. He's got esprit up to here. Right now, he is preparing to carry out his third mission of the night. His uniform is black as activated charcoal, filtering the very light out of the air. A bullet will bounce off its arachnofiber weave like a wren hitting a patio door, but excess perspiration wafts through it like a breeze through a freshly napalmed forest. Where his body has bony extremities, the suit has sintered armorgel: feels like gritty jello, protects like a stack of telephone books. When they gave him the job, they gave him a gun. The Deliverator never deals in cash, but someone might come after him anyway-might want his car, or his cargo. The gun is tiny, aero-styled, lightweight, the kind of a gun a fashion designer would carry; it fires teensy darts that fly at five times the velocity of an SR-71 spy plane, and when you get done using it, you have to plug it into the cigarette lighter, because it runs on electricity. The Deliverator never pulled that gun in anger, or in fear. He pulled it once in Gila Highlands. Some punks in Gila Highlands, a fancy Burbclave, wanted themselves a delivery, and they didn't want to pay for it. Thought they would impress the Deliverator with a baseball bat. The Deliverator took out his gun, centered its laser doohickey on that poised Louisville Slugger, fired it. The recoil was immense, as though the weapon had blown up in his hand. The middle third of the baseball bat turned into a column of burning sawdust accelerating in all directions like a bursting star. Punk ended up holding this bat handle with milky smoke pouring out the end. Stupid look on his face. Didn't get nothing but trouble from the Deliverator. Since then the Deliverator has kept the gun in the glove compartment and relied, instead, on a matched set of samurai swords, which have always been his weapon of choice anyhow. The punks in Gila Highlands weren't afraid of the gun, so the Deliverator was forced to use it. But swords need no demonstrations. The Deliverator's car has enough potential energy packed into its batteries to fire a pound of bacon into the asteroid Belt. Unlike a bimbo box or a Burb beater, the Deliverator's car unloads that power through gaping, gleaming, polished sphincters. When the Deiverator puts the hammer down, s**t happens. You want to talk contact patches? Your car's tires have tiny contact patches, talk to the thee asphalt in four places the size of your tongue. The Deliverator's car has big sticky tires with contact patches the size of a fat lady's thighs. The Deliverator is in touch with the road, starts like a bad day, stops on a peseta. Why is the Deliverator so equipped? Because people rely on him. He is a role model. This is America. People do whatever the f**k they feel like doing, you got a problem with that? Because they have a right to. And because they have guns and no one can f**king stop them. As a result, this country has one of the worst economies in the world. When it gets down to it—talking trade balances here—once we've brain-drained all our technology into other countries, once things have evened out, they're making cars in Bolivia and microwave ovens in Tadzhikistan and selling them here—once our edge in natural resources has been made irrelevant by giant Hong Kong ships and dirigibles that can ship North Dakota all the way to New Zealand for a nickel—once the Invisible Hand has taken all those historical inequities and smeared them out into a broad global layer of what a Pakistani brickmaker would consider to be prosperity—you know what? There's only four things we do better than anyone else: music movies microcode (software), high-speed pizza delvery The Deliverator used to make software. Still does, sometimes. But if life were a mellow elementary school run by well-meaning education Ph.D.s, the Deliverator's report card would say: "Hiro is so bright and creative but needs to work harder on his cooperation skills." So now he has this other job. No brightness or creativity involved—but no cooperation either. Just a single principle: the Deliverator stands tall, your pie in thirty minutes or you can have it free, shoot the driver, take his car, file a class-action suit. The Deliverator has been working this job for six months, a rich and lengthy tenure by his standards, and has never delivered a pizza in more than twenty-one minutes." """ encoder = HuffmanEncoder(sample_text) encoder.build_frequency_dictionary() encoder.build_priority_queue() PQ: PriorityQueue[str] = encoder.frequency_queue print(PQ) expected = [[1, "C"], [1, "O"], [1, "U"], [4, "A"], [1, ";"], [1, "K"], [1, "Z"], [4, "x"], [4, ":"], [1, "7"],\ [1, "1"], [2, "Y"], [2, "R"], [1, "I"], [1, ")"], [56, "v"], [42, "k"], [8, "z"], [4, "j"], [22, "\n"], [7, "S"],\ [3, "G"], [1, "L"], [21, "D"], [4, "P"], [4, "?"], [2, "q"], [10, "H"], [1, "("], [3, "\""], [1, "J"], [930, " "],\ [66, "p"], [263, "o"], [52, "f"], [208, "h"], [59, "b"], [84, "g"], [5, "W"], [320, "t"], [113, "d"], [207, "s"],\ [8, "-"], [224, "n"], [46, ","], [57, "w"], [8, "B"], [433, "e"], [96, "c"], [99, "u"], [6, "*"], [220, "r"], \ [43, "."], [63, "y"], [6, "—"], [279, "a"], [17, "T"], [157, "l"], [3, "N"], [272, "i"], [13, "\'"], [58, "m"]] self.assertFalse(PQ.is_empty(), "The priority queue should not be empty.") for i in range(len(PQ.my_tree)): self.assertEqual(expected[i][0], PQ.my_tree[i][0]) self.assertEqual(expected[i][1], PQ.my_tree[i][1].value)
def test_3_short_encode_decode(self): print( "-----------------------------------\nTesting short encode decode") douglas_adams = ( "There is an art to flying, or rather a knack. The knack lies in learning how to throw yourself at the ground and miss." ) encoder = HuffmanEncoder(douglas_adams) encoder.do_setup() encoded_flying_quote = encoder.encode_message(douglas_adams) decoded_flying_quote = encoder.decode_message(encoded_flying_quote) self.assertEqual(douglas_adams, decoded_flying_quote) print(decoded_flying_quote) print( f"Original size in ASCII: {8 * len(douglas_adams)} bits ({len(douglas_adams)} bytes)" ) print( f"encoded length: {len(encoded_flying_quote)} bits ({int(len(encoded_flying_quote) / 8+0.9)} bytes)" ) print( f"compression ratio: {len(encoded_flying_quote) / len(douglas_adams) / 8 * 100:3.2f}%" )
def test_PQ(self): """ tests whether a frequency dictionary is created correctly with a short piece of text. :return: """ encoder = HuffmanEncoder( "How much wood would a woodchuck chuck if a woodchuck could chuck wood?" ) encoder.build_frequency_dictionary() encoder.build_priority_queue() PQ: PriorityQueue[str] = encoder.frequency_queue expected = [[1, "H"], [1, "m"], [1, "i"], [5, "h"], [2, "l"], [4, "k"], [1, "f"], [12, " "], [6, "d"], [11, "o"], [2, "a"], [7, "u"], [6, "w"], [10, "c"], [1, "?"]] # expected_pq:PriorityQueue[str] = PriorityQueue[str](tree=expected, isMinHeap=True) self.assertFalse(PQ.is_empty(), "The priority queue should not be empty.") for i in range(len(PQ.my_tree)): self.assertEqual(expected[i][0], PQ.my_tree[i][0]) self.assertEqual(expected[i][1], PQ.my_tree[i][1].value)
def test_4_long_encode_decode(self): print( "-----------------------------------\nTesting long encode decode") gettysberg = ("Four score and seven years ago our fathers brought forth on this continent, a new nation, " \ "conceived in Liberty, and dedicated to the proposition that all men are created equal.\n" \ "Now we are engaged in a great civil war, testing whether that nation, or any nation so " \ "conceived and so dedicated, can long endure. We are met on a great battle-field of that " \ "war. We have come to dedicate a portion of that field, as a final resting place for those " \ "who here gave their lives that that nation might live. It is altogether fitting and proper " \ "that we should do this.\n" \ "But, in a larger sense, we can not dedicate -- we can not consecrate -- we can not hallow " \ "-- this ground. The brave men, living and dead, who struggled here, have consecrated it, " \ "far above our poor power to add or detract. The world will little note, nor long remember " \ "what we say here, but it can never forget what they did here. It is for us the living, " \ "rather, to be dedicated here to the unfinished work which they who fought here have thus " \ "far so nobly advanced. It is rather for us to be here dedicated to the great task remaining " \ "before us -- that from these honored dead we take increased devotion to that cause for which " \ "they gave the last full measure of devotion -- that we here highly resolve that these dead " \ "shall not have died in vain -- that this nation, under God, shall have a new birth of freedom " \ "-- and that government of the people, by the people, for the people, shall not perish from the " \ "earth.\nAbraham Lincoln\nNovember 19, 1863") encoder = HuffmanEncoder(gettysberg) encoder.do_setup() encoded_getty = encoder.encode_message(gettysberg) reset_getty = encoder.decode_message(encoded_getty) self.assertEqual(gettysberg, reset_getty) print(reset_getty) print( f"Original size in ASCII: {8 * len(gettysberg)} bits ({len(gettysberg)} bytes)" ) print( f"encoded length: {len(encoded_getty)} bits ({int(len(encoded_getty)/8+0.9)} bytes)" ) print( f"compression ratio: {(len(encoded_getty) / len(gettysberg) / 8 * 100):3.2f}%" )
def test_1_encode(self): print("-------------------------------------\nTesting encode.") encoder = HuffmanEncoder( "I'm here to kick butt and chew bubblegum. And I'm all out of bubblegum." ) encoder.build_frequency_dictionary() encoder.build_priority_queue() encoder.build_tree() encoder.build_encode_dictionary_with_tree() gibberish = encoder.encode_message( "I'm here to kick butt and chew bubblegum. And I'm all out of bubblegum." ) expected = [ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1 ] self.assertEqual(gibberish, expected, "Encoded text did not match.")
def test_encoder_exception(self): encoder = HuffmanEncoder("There can be only one.") encoder.build_frequency_dictionary() encoder.build_priority_queue() encoder.build_tree() encoder.build_encode_dictionary_with_tree() with self.assertRaises( KeyError, msg= "Encoder should raise a KeyError when encountering a letter not in the frequency dictionary." ): encoder.encode_message("Two to tango.")
def test_build_long(self): """ Tests whether we can build a encoder dictionary for a long piece of text. Sample text is the opening chapter of "Foundation" by Isaac Asimov, copyright 1951 :return: """ source_text = """ HARI SELDON—. . . born in the 11,988th year of the Galactic Era; died 12,069. The dates are more commonly given in terms of the current Foundational Era as -79 to the year 1 F.E. Born to middle-class parents on Helicon, Arcturus sector (where his father, in a legend of doubtful authenticity, was a tobacco grower in the hydroponic plants of the planet), he early showed amazing ability in mathematics. Anecdotes concerning his ability are innumerable, and some are contradictory. At the age of two, he is said to have . . . . . . Undoubtedly his greatest contributions were in the field of psychohistory. Seldon found the field little more than a set of vague axioms; he left it a profound statistical science. . . . . . . The best existing authority we have for the details of his life is the biography written by Gaal Dornick who, as a young man, met Seldon two years before the great mathematician's death. The story of the meeting . . . ENCYCLOPEDIA GALACTICA* Chapter One His name was Gaal Dornick and he was just a country boy who had never seen Trantor before. That is, not in real life. He had seen it many times on the hyper-video, and occasionally in tremendous three-dimensional newscasts covering an Imperial Coronation or the opening of a Galactic Council. Even though he had lived all his life on the world of Synnax, which circled a star at the edges of the Blue Drift, he was not cut off from civilization, you see. At that time, no place in the Galaxy was. There were nearly twenty-five million inhabited planets in the Galaxy then, and not one but owed allegiance to the Empire whose seat was on Trantor. It was the last half-century in which that could be said. To Gaal, this trip was the undoubted climax of his young, scholarly life. He had been in space before so that the trip, as a voyage and nothing more, meant little to him. To be sure, he had traveled previously only as far as Synnax's only satellite in order to get the data on the mechanics of meteor driftage which he needed for his dissertation, but space-travel was all one whether one travelled half a million miles, or as many light years. He had steeled himself just a little for the Jump through hyper-space, a phenomenon one did not experience in simple interplanetary trips. The Jump remained, and would probably remain forever, the only practical method of travelling between the stars. Travel through ordinary space could proceed at no rate more rapid than that of ordinary light (a bit of scientific knowledge that belonged among the items known since the forgotten dawn of human history), and that would have meant years of travel between even the nearest of inhabited systems. Through hyper-space, that unimaginable region that was neither space nor time, matter nor energy, something nor nothing, one could traverse the length of the Galaxy in the interval between two neighboring instants of time. Gaal had waited for the first of those jumps with a little dread curled gently in his stomach, and it ended in nothing more than a trifling jar, a little internal kick which ceased an instant before he could be sure he had felt it. That was all. And after that, there was only the ship, large and glistening; the cool production of 12,000 years of Imperial progress; and himself, with his doctorate in mathematics freshly obtained and an invitation from the great Hari Seldon to come to Trantor and join the vast and somewhat mysterious Seldon Project. What Gaal was waiting for after the disappointment of the Jump was that first sight of Trantor. He haunted the View-room. The steel shutter-lids were rolled back at announced times and he was always there, watching the hard brilliance of the stars, enjoying the incredible hazy swarm of a star cluster, like a giant conglomeration of fireflies caught in mid-motion and stilled forever. At one time there was the cold, blue-white smoke of a gaseous nebula within five light years of the ship, spreading over the window like distant milk, filling the room with an icy tinge, and disappearing out of sight two hours later, after another Jump. The first sight of Trantor's sun was that of a hard, white speck all but lost in a myriad such, and recognizable only because it was pointed out by the ship's guide. The stars were thick here near the Galactic center. But with each Jump, it shone more brightly, drowning out the rest, paling them and thinning them out. An officer came through and said, "View-room will be closed for the remainder of the trip. Prepare for landing." Gaal had followed after, clutching at the sleeve of the white uniform with the Spaceship-and-Sun of the Empire on it. He said, "Would it be possible to let me stay? I would like to see Trantor." The officer smiled and Gaal flushed a bit. It occurred to him that he spoke with a provincial accent. The officer said, "We'll be landing on Trantor by morning." "I mean I want to see it from Space." "Oh. Sorry, my boy. If this were a space-yacht we might manage it. But we're spinning down, sun-side. You wouldn't want to be blinded, burnt, and radiation-scarred all at the same time, would you?" Gaal started to walk away. The officer called after him, "Trantor would only be a gray blur anyway, Kid. Why don't you take a space-tour once you hit Trantor. They're cheap." Gaal looked back, "Thank you very much." It was childish to feel disappointed, but childishness comes almost as naturally to a man as to a child, and there was a lump in Gaal's throat. He had never seen Trantor spread out in all its incredibility, as large as life, and he hadn't expected to have to wait longer.""" encoder = HuffmanEncoder(source_text) encoder.build_frequency_dictionary() encoder.build_priority_queue() encoder.build_tree() encoder.build_encode_dictionary_with_tree() expected = {"\n" : [1, 0, 0, 1, 0, 1, 1], " " : [1, 1, 1], "\"" : [1, 1, 0, 0, 1, 1, 0, 1, 1],\ "\'" : [1, 0, 0, 1, 0, 1, 0, 1, 0], "(" : [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],\ ")" : [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1], "*" : [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0],\ "," : [1, 1, 0, 1, 1, 1, 1], "-" : [0, 1, 0, 0, 1, 1, 1, 1], "." : [0, 1, 0, 0, 0, 1],\ "0" : [1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1], "1" : [0, 1, 0, 0, 1, 1, 1, 0, 0, 0], \ "2" : [1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0], "6" : [0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1],\ "7" : [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1], "8" : [0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1],\ "9" : [1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0], ";" : [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1],\ "?" : [0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0], "A" : [1, 1, 0, 0, 1, 1, 0, 0, 0],\ "B" : [1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1], "C" : [1, 1, 0, 1, 1, 1, 0, 0, 0, 0],\ "D" : [0, 1, 0, 0, 1, 1, 0, 1, 1, 1], "E" : [0, 1, 0, 0, 0, 0, 0, 1, 1],\ "F" : [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1], "G" : [0, 1, 0, 0, 1, 1, 0, 0],\ "H" : [0, 1, 0, 0, 1, 1, 0, 1, 0], "I" : [1, 1, 0, 0, 1, 1, 0, 0, 1],\ "J" : [0, 1, 0, 0, 1, 1, 0, 1, 1, 0], "K" : [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],\ "L" : [0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1], "N" : [0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0],\ "O" : [1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0], "P" : [1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1],\ "R" : [0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0], "S" : [1, 0, 0, 1, 0, 1, 0, 1, 1],\ "T" : [1, 1, 0, 1, 1, 1, 0, 1], "U" : [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1], \ "V" : [1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1], "W" : [0, 1, 0, 0, 0, 0, 0, 0, 1, 1],\ "Y" : [0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0], "a" : [1, 0, 1, 0], "b" : [1, 1, 0, 0, 1, 1, 1],\ "c" : [1, 1, 0, 1, 1, 0], "d" : [1, 0, 0, 0, 0], "e" : [0, 0, 0], "f" : [1, 0, 0, 1, 1, 1],\ "g" : [1, 0, 0, 0, 1, 0], "h" : [0, 0, 1, 0], "i" : [0, 1, 1, 0], \ "j" : [1, 1, 0, 0, 1, 1, 0, 1, 0, 1], "k" : [1, 0, 0, 1, 0, 1, 0, 0], "l" : [1, 1, 0, 0, 0],\ "m" : [1, 1, 0, 0, 1, 0], "n" : [0, 1, 0, 1], "o" : [0, 1, 1, 1], "p" : [0, 1, 0, 0, 1, 0],\ "r" : [0, 0, 1, 1], "s" : [1, 1, 0, 1, 0], "t" : [1, 0, 1, 1], "u" : [1, 0, 0, 1, 1, 0], \ "v" : [0, 1, 0, 0, 0, 0, 1], "w" : [1, 0, 0, 1, 0, 0], "x" : [0, 1, 0, 0, 1, 1, 1, 0, 1],\ "y" : [1, 0, 0, 0, 1, 1], "z" : [0, 1, 0, 0, 0, 0, 0, 1, 0, 1],\ "—" : [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0]} self.assertEqual( len(expected), len(encoder.encode_dictionary), "expected and encoder have different number of keys.") for item in encoder.encode_dictionary.keys(): self.assertTrue(item in expected, "unexpected key in the encode_dictionary") self.assertEqual(expected[item], encoder.encode_dictionary[item], f"Value for {item} did not match.")
def test_build_tree(self): encoder = HuffmanEncoder("May the force be with you, always.") encoder.build_frequency_dictionary() encoder.build_priority_queue() encoder.build_tree() print("This is your tree:") encoder.encoding_tree.print_tree() print("----------------------------------------") print("This is what Mr. Howe's looked like.") print(""" [i] < [u] < [b] < [y] < [o] < [M] < [.] < [f] < [,] < [h] < [l] < [s] < [t] < [w] < [r] < [c] < [ ] < [e] < [a] ----------------------------------------- """) encoder.build_encode_dictionary_with_tree() expected = {"a": [1, 1, 1, 1],"b": [0, 0, 0, 1, 1],"c": [1, 0, 1, 1, 1],"e": [1, 1, 1, 0],"f": [0, 1, 1, 0, 0],\ "h": [0, 1, 1, 1],"i": [0, 0, 0, 0],"l": [1, 0, 0, 0, 0],"M": [0, 1, 0, 1, 0],"o": [0, 1, 0, 0], "r": [1, 0, 1, 1, 0], "s": [1, 0, 0, 0, 1],"t": [1, 0, 0, 1],"u": [0, 0, 0, 1, 0],"w": [1, 0, 1, 0], "y": [0, 0, 1], " ": [1, 1, 0],".": [0, 1, 0, 1, 1],",": [0, 1, 1, 0, 1]} self.assertEqual( len(expected), len(encoder.encode_dictionary), "expected and encoder have different number of keys.") for item in sorted(encoder.encode_dictionary.keys()): print(f"\"{item}\" : {encoder.encode_dictionary[item]}") self.assertTrue(item in expected, "unexpected key in the encode_dictionary") self.assertEqual(expected[item], encoder.encode_dictionary[item], f"Value for {item} did not match.")