# Copyright (C) 2009, Tutorius.org # Copyright (C) 2009, Erick Lavoie # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ Tutorial Tests """ # TODO: Add tests for 47, 52, 55, 109, 132, 175, 209, 229, 233, 271, 274, 292, 295, 318, 337, 375, 394, 411, 428, 446, 480, 491, 624, 637, 698 # TODO: Use doc strings for test names that are too long # TODO: Use helper functions for common checks import unittest from sugar.tutorius.tutorial import * # The following tests are organized around 4 classes: # # Black box tests: # Those tests should limit themselves to exercise the # interface of the object so everything should be tested # only through the interface the object offers. This will # ease test maintenance since we anticipate most changes # will be about the implementation of an object and not # its interface. # # Tests definitions are written assuming the previous tests # did complete correctly so the number of things to assert # is minimal. # # Basic interface cases: # Test the interface of the object for trivial cases # just to assert that the functionality this object # offers really works # # Limit cases: # Test edge cases that cover more obscure usage # scenarios but that should be valid nonetheless # # Error cases: # Test wrong inputs to make sure that the object is hard # to misuse and do generate proper errors # # White box tests: # Those should be used only for really important algorithms # to make sure they behave correctly in every cases, otherwise # the tests will break each time we change something in the # implementation from sugar.tutorius.properties import * class MockAction(TPropContainer): i = TIntProperty(0, 0, 9) class MockEvent(TPropContainer): i = TIntProperty(0, 0, 9) class StateTest(unittest.TestCase): """Test basic functionalities of states used by tutorials""" def setUp(self): self.state = State("State1") self.action = MockAction() self.event = MockEvent() def tearDown(self): pass ######################### Basic interface cases ######################### #### Action def test_add_dummy_action(self): action_name = self.state.add_action("action1") assert action_name assert len(self.state.get_action_dict()) == 1 assert self.state.get_action_dict().has_key(action_name) assert self.state.get_action_dict()[action_name] == "action1" def test_add_generate_unique_action_names(self): action_name1 = self.state.add_action("action1") action_name2 = self.state.add_action("action2") assert action_name1 and action_name2 assert action_name1 != action_name2 def test_update_dummy_action(self): action_name = self.state.add_action(self.action) assert self.action.i == 0 prop = self.action.get_properties_dict_copy() prop["i"] = 2 self.state.update_action(action_name, prop) assert len(self.state.get_action_dict()) == 1 assert self.state.get_action_dict().has_key(action_name) assert self.state.get_action_dict()[action_name].get_properties_dict_copy() == prop def test_delete_dummy_action(self): action_name = self.state.add_action("action1") assert len(self.state.get_action_dict()) == 1 assert self.state.get_action_dict().has_key(action_name) assert self.state.get_action_dict()[action_name] == "action1" self.state.delete_action(action_name) assert len(self.state.get_action_dict()) == 0 def test_delete_all_dummy_actions(self): action_name = self.state.add_action("action1") assert len(self.state.get_action_dict()) == 1 assert self.state.get_action_dict().has_key(action_name) assert self.state.get_action_dict()[action_name] == "action1" self.state.delete_actions() assert len(self.state.get_action_dict()) == 0 #### Transition def test_add_dummy_transition(self): transition_name = self.state.add_transition("transition1") assert len(self.state.get_transition_dict()) == 1 assert self.state.get_transition_dict().has_key(transition_name) assert self.state.get_transition_dict()[transition_name] == "transition1" def test_add_generate_unique_transition_names(self): transition_name1 = self.state.add_transition("transition1") transition_name2 = self.state.add_transition("transition2") assert transition_name1 != transition_name2 def test_update_dummy_transition(self): transition_name = self.state.add_transition((self.event, Tutorial.END)) assert self.event.i == 0 prop = self.event.get_properties_dict_copy() prop["i"] = 2 self.state.update_transition(transition_name, prop) assert len(self.state.get_transition_dict()) == 1 assert self.state.get_transition_dict().has_key(transition_name) assert self.state.get_transition_dict()[transition_name][0].get_properties_dict_copy() == prop assert self.state.get_transition_dict()[transition_name][1] == Tutorial.END # Now update only the transition self.state.update_transition(transition_name, new_state=Tutorial.INIT) assert self.state.get_transition_dict()[transition_name][0].get_properties_dict_copy() == prop assert self.state.get_transition_dict()[transition_name][1] == Tutorial.INIT def test_delete_dummy_transition(self): transition_name = self.state.add_transition("transition1") assert len(self.state.get_transition_dict()) == 1 assert self.state.get_transition_dict().has_key(transition_name) assert self.state.get_transition_dict()[transition_name] == "transition1" self.state.delete_transition(transition_name) assert len(self.state.get_transition_dict()) == 0 def test_delete_all_dummy_transitions(self): transition_name = self.state.add_transition("transition1") assert len(self.state.get_transition_dict()) == 1 assert self.state.get_transition_dict().has_key(transition_name) assert self.state.get_transition_dict()[transition_name] == "transition1" self.state.delete_transitions() assert len(self.state.get_transition_dict()) == 0 ######################### Limit cases ################################### #### Action #### Transition ######################### Error cases ################################### #### Action def test_update_unknown_action(self): try: self.state.update_action("unknown_name", "action") assert False except LookupError: pass def test_delete_unknown_action(self): try: self.state.delete_action("unknown_name") assert False except LookupError: pass #### Transition def test_add_existing_transition(self): self.state.add_transition("transition") try: self.state.add_transition("transition") assert False except TransitionAlreadyExists: pass class TutorialTest(unittest.TestCase): """Test tutorial functionality""" def setUp(self): self.tutorial = Tutorial("Tutorial Test") self.action = MockAction() self.event = MockEvent() def tearDown(self): pass ######################### Basic interface cases ######################### #### Tutorial def test_default_initial_value_in_tutorial(self): assert len(self.tutorial.get_state_dict()) == 2 assert set(self.tutorial.get_state_dict().keys()) == set([Tutorial.INIT,Tutorial.END]) assert len(self.tutorial.get_action_dict()) == 0 assert len(self.tutorial.get_transition_dict()) == 1 assert self.tutorial.get_previous_states_dict(Tutorial.INIT) == {} assert self.tutorial.get_following_states_dict(Tutorial.INIT).keys() == [Tutorial.END] assert self.tutorial.get_previous_states_dict(Tutorial.END).keys() == [Tutorial.INIT] assert self.tutorial.get_following_states_dict(Tutorial.END) == {} #### State def test_add_default_state(self): state_name = self.tutorial.add_state() assert state_name assert len(self.tutorial.get_state_dict()) == 3 assert set(self.tutorial.get_state_dict().keys()) == set([Tutorial.INIT,Tutorial.END, state_name]) assert len(self.tutorial.get_action_dict()) == 0 assert len(self.tutorial.get_transition_dict()) == 1 def test_add_state_with_action(self): state_name = self.tutorial.add_state(action_list=["action1"]) assert state_name assert len(self.tutorial.get_state_dict()) == 3 assert set(self.tutorial.get_state_dict().keys()) == set([Tutorial.INIT,Tutorial.END, state_name]) assert len(self.tutorial.get_action_dict()) == 1 assert len(self.tutorial.get_transition_dict()) == 1 def test_add_state_with_transition(self): state_name = self.tutorial.add_state(transition_list=[("event1",Tutorial.END)]) assert state_name assert len(self.tutorial.get_state_dict()) == 3 assert set(self.tutorial.get_state_dict().keys()) == set([Tutorial.INIT,Tutorial.END, state_name]) assert len(self.tutorial.get_action_dict()) == 0 assert len(self.tutorial.get_transition_dict()) == 2 def test_add_generate_unique_state_names(self): state_name1 = self.tutorial.add_state() state_name2 = self.tutorial.add_state() assert state_name1 and state_name2 assert state_name1 != state_name2 def test_delete_lone_state(self): state_name1 = self.tutorial.add_state() self.tutorial.delete_state(state_name1) assert len(self.tutorial.get_state_dict()) == 2 assert set(self.tutorial.get_state_dict().keys()) == set([Tutorial.INIT,Tutorial.END]) assert len(self.tutorial.get_action_dict()) == 0 assert len(self.tutorial.get_transition_dict()) == 1 assert self.tutorial.get_previous_states_dict(Tutorial.INIT) == {} assert self.tutorial.get_following_states_dict(Tutorial.INIT).keys() == [Tutorial.END] assert self.tutorial.get_previous_states_dict(Tutorial.END).keys() == [Tutorial.INIT] assert self.tutorial.get_following_states_dict(Tutorial.END) == {} def test_delete_linked_state(self): state_name1 = self.tutorial.add_state() self.tutorial.update_transition(Tutorial.INITIAL_TRANSITION_NAME, \ None, state_name1) transition_name1 = self.tutorial.add_transition(state_name1,("event1", Tutorial.END)) self.tutorial.delete_state(state_name1) assert len(self.tutorial.get_state_dict()) == 2 assert set(self.tutorial.get_state_dict().keys()) == set([Tutorial.INIT,Tutorial.END]) assert len(self.tutorial.get_action_dict()) == 0 assert len(self.tutorial.get_transition_dict()) == 1 assert self.tutorial.get_previous_states_dict(Tutorial.INIT) == {} assert self.tutorial.get_following_states_dict(Tutorial.INIT).keys() == [Tutorial.END] assert self.tutorial.get_previous_states_dict(Tutorial.END).keys() == [Tutorial.INIT] assert self.tutorial.get_following_states_dict(Tutorial.END) == {} #### Action def test_add_dummy_action(self): state_name = self.tutorial.add_state() action_name = self.tutorial.add_action(state_name,"action1") assert action_name assert len(self.tutorial.get_action_dict()) == 1 assert self.tutorial.get_action_dict().has_key(action_name) assert self.tutorial.get_action_dict()[action_name] == "action1" def test_add_generate_unique_action_names(self): state_name = self.tutorial.add_state() action_name1 = self.tutorial.add_action(state_name,"action1") action_name2 = self.tutorial.add_action(state_name,"action2") assert action_name1 and action_name2 assert action_name1 != action_name2 def test_update_dummy_action(self): state_name = self.tutorial.add_state() action_name = self.tutorial.add_action(state_name,self.action) prop = self.action.get_properties_dict_copy() prop["i"] = 2 self.tutorial.update_action(action_name, prop) assert len(self.tutorial.get_action_dict()) == 1 assert self.tutorial.get_action_dict().has_key(action_name) assert self.tutorial.get_action_dict()[action_name].get_properties_dict_copy() == prop def test_delete_dummy_action(self): state_name = self.tutorial.add_state() action_name = self.tutorial.add_action(state_name,"action1") assert len(self.tutorial.get_action_dict()) == 1 assert self.tutorial.get_action_dict().has_key(action_name) assert self.tutorial.get_action_dict()[action_name] == "action1" self.tutorial.delete_action(action_name) assert len(self.tutorial.get_action_dict()) == 0 #### Transition def test_add_dummy_transition(self): state_name = self.tutorial.add_state() transition_name = self.tutorial.add_transition(state_name,"transition1") assert len(self.tutorial.get_transition_dict()) == 2 assert self.tutorial.get_transition_dict().has_key(transition_name) assert self.tutorial.get_transition_dict()[transition_name] == "transition1" def test_add_generate_unique_transition_names(self): state_name = self.tutorial.add_state() transition_name1 = self.tutorial.add_transition(state_name,"transition1") transition_name2 = self.tutorial.add_transition(state_name,"transition2") assert transition_name1 and transition_name2 assert transition_name1 != transition_name2 def test_update_dummy_transition(self): state_name = self.tutorial.add_state() transition_name = self.tutorial.add_transition(state_name,(self.event, Tutorial.END)) prop = self.event.get_properties_dict_copy() prop["i"] = 2 self.tutorial.update_transition(transition_name, prop) assert len(self.tutorial.get_transition_dict()) == 2 assert self.tutorial.get_transition_dict().has_key(transition_name) assert self.tutorial.get_transition_dict()[transition_name][0].get_properties_dict_copy() == prop assert self.tutorial.get_transition_dict()[transition_name][1] == Tutorial.END # Now update only the transition self.tutorial.update_transition(transition_name, new_state=Tutorial.INIT) assert self.tutorial.get_transition_dict()[transition_name][0].get_properties_dict_copy() == prop assert self.tutorial.get_transition_dict()[transition_name][1] == Tutorial.INIT def test_delete_dummy_transition(self): state_name = self.tutorial.add_state() transition_name = self.tutorial.add_transition(state_name,"transition1") assert len(self.tutorial.get_transition_dict()) == 2 assert self.tutorial.get_transition_dict().has_key(transition_name) assert self.tutorial.get_transition_dict()[transition_name] == "transition1" self.tutorial.delete_transition(transition_name) assert len(self.tutorial.get_transition_dict()) == 1 ######################### Limit cases ################################### #### Tutorial #### State #### Action #### Transition ######################### Error cases ################################### #### Tutorial #### State #### Action def test_update_unknown_action(self): lookup_error = None try: self.tutorial.update_action("unknown_name", "action") except LookupError, e: lookup_error = e assert lookup_error def test_delete_unknown_action(self): lookup_error = None try: self.tutorial.delete_action("unknown_name") except LookupError, e: lookup_error = e assert lookup_error #### Transition def test_add_existing_transition(self): self.tutorial.add_transition(Tutorial.INIT,("event","transition")) transition_exists_error = None try: self.tutorial.add_transition(Tutorial.INIT,("event","transition")) except TransitionAlreadyExists, e: transition_exists_error = e assert transition_exists_error if __name__ == "__main__": unittest.main()