Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/sugar/tutorius/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/sugar/tutorius/tests')
-rw-r--r--src/sugar/tutorius/tests/actiontests.py22
-rw-r--r--src/sugar/tutorius/tests/bundlertests.py65
-rw-r--r--src/sugar/tutorius/tests/constraintstests.py38
-rw-r--r--src/sugar/tutorius/tests/coretests.py41
-rw-r--r--src/sugar/tutorius/tests/propertiestests.py34
-rwxr-xr-xsrc/sugar/tutorius/tests/run-tests.py6
-rw-r--r--src/sugar/tutorius/tests/serializertests.py196
7 files changed, 375 insertions, 27 deletions
diff --git a/src/sugar/tutorius/tests/actiontests.py b/src/sugar/tutorius/tests/actiontests.py
index bce753e..d244547 100644
--- a/src/sugar/tutorius/tests/actiontests.py
+++ b/src/sugar/tutorius/tests/actiontests.py
@@ -52,6 +52,28 @@ class PropsTest(unittest.TestCase):
for prop_name in act.get_properties():
assert act.properties[prop_name].value == test_props[prop_name], "Wrong initial value for property %s : %s"%(prop_name,str(act.properties[prop_name]))
+
+class DialogMessageTest(unittest.TestCase):
+ def setUp(self):
+ self.dial = DialogMessage("Message text", [200, 300])
+
+ def test_properties(self):
+ assert self.dial.message.value == "Message text", "Wrong start value for the message"
+
+ assert self.dial.position.value == [200, 300], "Wrong start value for the position"
+
+class BubbleMessageTest(unittest.TestCase):
+ def setUp(self):
+ self.bubble = BubbleMessage(message="Message text", pos=[200, 300], tailpos=[-15, -25])
+
+ def test_properties(self):
+ props = self.bubble.get_properties()
+
+ assert "message" in props, 'No message property of BubbleMessage'
+
+ assert "position" in props, 'No position property in BubbleMessage'
+
+ assert "tail_pos" in props, 'No tail position property in BubbleMessage'
class CountAction(Action):
diff --git a/src/sugar/tutorius/tests/bundlertests.py b/src/sugar/tutorius/tests/bundlertests.py
new file mode 100644
index 0000000..8da2310
--- /dev/null
+++ b/src/sugar/tutorius/tests/bundlertests.py
@@ -0,0 +1,65 @@
+# Copyright (C) 2009, Tutorius.org
+# Copyright (C) 2009, Charles-Etienne Carriere <iso.swiffer@gmail.com>
+#
+# 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
+"""
+Bundler tests
+
+This module contains all the tests for the storage mecanisms for tutorials
+This mean testing savins and loading tutorial, .ini file management and
+adding ressources to tutorial
+"""
+
+import unittest
+import os
+import uuid
+
+from sugar.tutorius import bundler
+
+class TutorialBundlerTests(unittest.TestCase):
+
+ def setUp(self):
+
+ #generate a test GUID
+ self.test_guid = uuid.uuid1()
+ self.guid_path = os.path.join(bundler._get_store_root(),str(self.test_guid))
+ os.mkdir(self.guid_path)
+
+ self.ini_file = os.path.join(self.guid_path, "meta.ini")
+
+ f = open(self.ini_file,'w')
+ f.write("[GENERAL_METADATA]")
+ f.write(os.linesep)
+ f.write("GUID:")
+ f.write(str(self.test_guid))
+ f.close()
+
+ def tearDown(self):
+ os.remove(self.ini_file)
+ os.rmdir(self.guid_path)
+
+ def test_add_ressource(self):
+ bund = bundler.TutorialBundler(self.test_guid)
+
+ temp_file = open("test.txt",'w')
+ temp_file.write('test')
+ temp_file.close()
+
+ bund.add_resource("test.txt")
+
+ assert os.path.exists(os.path.join(self.guid_path,"test.txt")), "add_ressource did not create the file"
+
+if __name__ == "__main__":
+ unittest.main() \ No newline at end of file
diff --git a/src/sugar/tutorius/tests/constraintstests.py b/src/sugar/tutorius/tests/constraintstests.py
index 407cc24..b7b0a47 100644
--- a/src/sugar/tutorius/tests/constraintstests.py
+++ b/src/sugar/tutorius/tests/constraintstests.py
@@ -77,28 +77,50 @@ class LowerLimitConstraintTest(unittest.TestCase):
except LowerLimitConstraintError:
assert True, "Validation of LowerLimit(10) on 20 should not raise an exception"
-class SizeConstraintTest(unittest.TestCase):
+class MaxSizeConstraintTest(unittest.TestCase):
def test_empty_constraint(self):
- cons = SizeConstraint(None)
+ cons = MaxSizeConstraint(None)
try:
cons.validate(20)
- except SizeConstraintError:
+ except MaxSizeConstraintError:
assert False, "Empty contraint should not raise an exception"
def test_validate(self):
- cons = SizeConstraint(10)
+ cons = MaxSizeConstraint(10)
try:
cons.validate(range(0, 20))
- assert False, "Validation of SizeLimit(10) on list of length 20 should raise an exception"
- except SizeConstraintError:
+ assert False, "Validation of MaxSizeConstraint(10) on list of length 20 should raise an exception"
+ except MaxSizeConstraintError:
pass
try:
cons.validate(range(0,5))
- except SizeConstraintError:
- assert True, "Validation of SizeLimit(10) on list of length 5 should not raise an exception"
+ except MaxSizeConstraintError:
+ assert True, "Validation of MaxSizeConstraint(10) on list of length 5 should not raise an exception"
+class MinSizeConstraintTest(unittest.TestCase):
+ def test_empty_constraint(self):
+ cons = MinSizeConstraint(None)
+ try:
+ cons.validate(20)
+ except MinSizeConstraintError:
+ assert False, "Empty contraint should not raise an exception"
+
+ def test_validate(self):
+ cons = MinSizeConstraint(10)
+
+ try:
+ cons.validate(range(0, 5))
+ assert False, "Validation of MinSizeConstraint(10) on list of length 20 should raise an exception"
+ except MinSizeConstraintError:
+ pass
+
+ try:
+ cons.validate(range(0,20))
+ except MinSizeConstraintError:
+ assert True, "Validation of MinSizeConstraint(10) on list of length 5 should not raise an exception"
+
class ColorConstraintTest(unittest.TestCase):
def test_validate(self):
cons = ColorConstraint()
diff --git a/src/sugar/tutorius/tests/coretests.py b/src/sugar/tutorius/tests/coretests.py
index 5f91a64..c27846d 100644
--- a/src/sugar/tutorius/tests/coretests.py
+++ b/src/sugar/tutorius/tests/coretests.py
@@ -18,7 +18,7 @@
Core Tests
This module contains all the tests that pertain to the usage of the Tutorius
-Core. This means that the the Finite State Machine, States and all the
+Core. This means that the Event Filters, the Finite State Machine and all the
related elements and interfaces are tested here.
Usage of actions and event filters is tested, but not the concrete actions
@@ -29,7 +29,7 @@ and event filters. Those are in their separate test module
import unittest
import logging
-from sugar.tutorius.actions import Action, ClickAction, TypeTextAction
+from sugar.tutorius.actions import Action, OnceWrapper, ClickAction, TypeTextAction
from sugar.tutorius.core import *
from sugar.tutorius.filters import *
@@ -49,6 +49,14 @@ class SimpleTutorial(Tutorial):
def set_state(self, name):
self.current_state_name = name
+class TutorialWithFSM(Tutorial):
+ """
+ Fake tutorial, but associated with a FSM.
+ """
+ def __init__(self, start_name="INIT", fsm=None):
+ Tutorial.__init__(self, start_name, fsm)
+ self.activity = activity.Activity()
+
class TrueWhileActiveAction(Action):
"""
This action's active member is set to True after a do and to False after
@@ -483,7 +491,6 @@ class FSMTest(unittest.TestCase):
except Exception:
assert False, "Removing a non-existing state dit not throw the right kind of exception"
-
# Now try removing the second state
fsm.remove_state("second")
@@ -502,6 +509,33 @@ class FSMTest(unittest.TestCase):
assert "second" not in fsm.get_following_states("third"),\
"The link to second from third still exists after removal"
+ def test_set_same_state(self):
+ fsm = FiniteStateMachine("Set same state")
+
+ st1 = State("INIT")
+ st1.add_action(CountAction())
+
+ fsm.add_state(st1)
+
+ tut = SimpleTutorial()
+
+ fsm.set_tutorial(tut)
+
+ fsm.set_state("INIT")
+
+ assert fsm.get_state_by_name("INIT").get_action_list()[0].do_count == 1, \
+ "The action was not triggered on 'INIT'"
+
+ fsm.set_state("INIT")
+
+ do_count = fsm.get_state_by_name("INIT").get_action_list()[0].do_count
+ assert fsm.get_state_by_name("INIT").get_action_list()[0].do_count == 1, \
+ "The action was triggered a second time, do_count = %d"%do_count
+
+ undo_count = fsm.get_state_by_name("INIT").get_action_list()[0].undo_count
+ assert fsm.get_state_by_name("INIT").get_action_list()[0].undo_count == 0,\
+ "The action has been undone unappropriately, undo_count = %d"%undo_count
+
class FSMExplorationTests(unittest.TestCase):
def setUp(self):
self.buildFSM()
@@ -556,6 +590,7 @@ class FSMExplorationTests(unittest.TestCase):
self.validate_previous_states("Third", ("INIT", "Second"))
self.validate_previous_states("Fourth", ("Second"))
+
if __name__ == "__main__":
unittest.main()
diff --git a/src/sugar/tutorius/tests/propertiestests.py b/src/sugar/tutorius/tests/propertiestests.py
index 4f4caac..45ba264 100644
--- a/src/sugar/tutorius/tests/propertiestests.py
+++ b/src/sugar/tutorius/tests/propertiestests.py
@@ -204,7 +204,7 @@ class TStringPropertyTest(unittest.TestCase):
try:
prop.set("My string is too big!")
assert False, "String should not set to longer than max size"
- except SizeConstraintError:
+ except MaxSizeConstraintError:
pass
except:
assert False, "Wrong exception type thrown"
@@ -218,7 +218,7 @@ class TStringPropertyTest(unittest.TestCase):
try:
prop = TStringProperty("This is normal", 5)
assert False, "Creation of the property should fail."
- except SizeConstraintError:
+ except MaxSizeConstraintError:
pass
except:
assert False, "Wrong exception type on failed constructor"
@@ -236,26 +236,34 @@ class TArrayPropertyTest(unittest.TestCase):
try_wrong_values(prop)
- def test_size_limit(self):
- prop = TArrayProperty([1,2], 4)
+ def test_size_limits(self):
+ prop = TArrayProperty([1,2], None, 4)
try:
prop.set([1,2,4,5,6,7])
- assert False, "Size limit constraint was not properly applied"
- except SizeConstraintError:
+ assert False, "Maximum size limit constraint was not properly applied"
+ except MaxSizeConstraintError:
+ pass
+
+ prop = TArrayProperty([1,2,3,4], 2)
+
+ try:
+ prop.set([1])
+ assert False, "Minimum size limit constraint was not properly applied"
+ except MinSizeConstraintError:
pass
- except:
- assert False, "Wrong type of exception thrown"
-
def test_failing_constructor(self):
try:
- prop = TArrayProperty([100, 0, 20], 2)
+ prop = TArrayProperty([100, 0, 20], None, 2)
assert False, "Creation of the property should fail."
- except SizeConstraintError:
+ except MaxSizeConstraintError:
+ pass
+ try:
+ prop = TArrayProperty([100, 0, 20], 4, None)
+ assert False, "Creation of the property should fail."
+ except MinSizeConstraintError:
pass
- except:
- assert False, "Wrong exception type on failed constructor"
class TColorPropertyTest(unittest.TestCase):
def test_basic_color(self):
diff --git a/src/sugar/tutorius/tests/run-tests.py b/src/sugar/tutorius/tests/run-tests.py
index 87edd57..042b10e 100755
--- a/src/sugar/tutorius/tests/run-tests.py
+++ b/src/sugar/tutorius/tests/run-tests.py
@@ -14,7 +14,6 @@ SUBDIRS = ["uam"]
GLOB_PATH = os.path.join(FULL_PATH,"*.py")
import unittest
from glob import glob
-
def report_files():
ret = glob(GLOB_PATH)
for dir in SUBDIRS:
@@ -40,6 +39,7 @@ if __name__=='__main__':
import filterstests
import constraintstests
import propertiestests
+ import serializertests
suite = unittest.TestSuite()
suite.addTests(unittest.findTestCases(coretests))
suite.addTests(unittest.findTestCases(servicestests))
@@ -51,10 +51,9 @@ if __name__=='__main__':
suite.addTests(unittest.findTestCases(filterstests))
suite.addTests(unittest.findTestCases(constraintstests))
suite.addTests(unittest.findTestCases(propertiestests))
-
+ suite.addTests(unittest.findTestCases(serializertests))
runner = unittest.TextTestRunner()
runner.run(suite)
-
coverage.stop()
coverage.report(report_files())
coverage.erase()
@@ -70,5 +69,6 @@ if __name__=='__main__':
from constraintstests import *
from propertiestests import *
from actiontests import *
+ from serializertests import *
unittest.main()
diff --git a/src/sugar/tutorius/tests/serializertests.py b/src/sugar/tutorius/tests/serializertests.py
new file mode 100644
index 0000000..bc29601
--- /dev/null
+++ b/src/sugar/tutorius/tests/serializertests.py
@@ -0,0 +1,196 @@
+# Copyright (C) 2009, Tutorius.org
+# Copyright (C) 2009, Jean-Christophe Savard <savard.jean.christophe@gmail.com>
+#
+# 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
+"""
+Serialization Tests
+
+This module contains all the tests that pertain to the usage of the Tutorius
+Serializer object. This means testing saving a tutorial dictionary to a .tml
+file, loading the list of tutorials for this activity and building chosen
+tutorial.
+"""
+
+import unittest
+
+import logging
+import linecache
+import os
+import shutil
+
+from sugar.tutorius import gtkutils, overlayer
+from sugar.tutorius.core import Tutorial, State, FiniteStateMachine
+from sugar.tutorius.actions import *
+from sugar.tutorius.filters import *
+from sugar.tutorius.bundler import XMLSerializer, Serializer
+import sugar
+from uuid import *
+import rpdb2
+
+class SerializerInterfaceTest(unittest.TestCase):
+ """
+ For completeness' sake.
+ """
+ def test_save(self):
+ ser = Serializer()
+
+ try:
+ ser.save_fsm(None)
+ assert False, "save_fsm() should throw an unimplemented error"
+ except:
+ pass
+
+ def test_load(self):
+ ser = Serializer()
+
+ try:
+ ser.load_fsm(str(uuid.uuid1()))
+ assert False, "load_fsm() should throw an unimplemented error"
+ except:
+ pass
+
+class XMLSerializerTest(unittest.TestCase):
+ """
+ Tests the transformation of XML to FSM, then back.
+ """
+ def setUp(self):
+ # Make the serializer believe the test is in a activity path
+ self.testpath = "/tmp/testdata/"
+ os.environ["SUGAR_BUNDLE_PATH"] = self.testpath
+ os.environ["SUGAR_PREFIX"] = self.testpath
+## os.mkdir(sugar.tutorius.bundler._get_store_root())
+
+ # Create the sample FSM
+ self.fsm = FiniteStateMachine("testingMachine")
+
+ # Add a few states
+ act1 = BubbleMessage(message="Hi", pos=[300, 450])
+ ev1 = GtkWidgetEventFilter("0.12.31.2.2", "clicked", "Second")
+ act2 = BubbleMessage(message="Second message", pos=[250, 150], tailpos=[1,2])
+
+ st1 = State("INIT")
+ st1.add_action(act1)
+ st1.add_event_filter(ev1)
+
+ st2 = State("Second")
+
+ st2.add_action(act2)
+
+ self.fsm.add_state(st1)
+ self.fsm.add_state(st2)
+
+ self.uuid = uuid1()
+
+ # Flag to set to True if the output can be deleted after execution of
+ # the test
+ self.remove = True
+
+ def tearDown(self):
+ """
+ Removes the created files, if need be.
+ """
+ if self.remove == True:
+ os.remove(os.path.join(sugar.tutorius.bundler._get_store_root(), str(self.uuid)) + "/fsm.xml")
+ if os.path.isdir(self.testpath):
+ shutil.rmtree(self.testpath)
+
+ def test_save(self):
+ """
+ Writes an FSM to disk, then compares the file to the expected results.
+ "Remove" boolean argument specify if the test data must be removed or not
+ """
+ xml_ser = XMLSerializer()
+ os.makedirs(os.path.join(sugar.tutorius.bundler._get_store_root(), str(self.uuid)))
+ #rpdb2.start_embedded_debugger('flakyPass')
+ xml_ser.save_fsm(self.fsm, "fsm.xml", os.path.join(sugar.tutorius.bundler._get_store_root(), str(self.uuid)))
+
+ def test_save_and_load(self):
+ """
+ Load up the written FSM and compare it with the object representation.
+ """
+ self.test_save()
+ testpath = "/tmp/testdata/"
+ #rpdb2.start_embedded_debugger('flakyPass')
+ xml_ser = XMLSerializer()
+
+ # This interface needs to be redone... It's not clean because there is
+ # a responsibility mixup between the XML reader and the bundler.
+ loaded_fsm = xml_ser.load_fsm(str(self.uuid))
+
+ # Compare the two FSMs
+ assert loaded_fsm._states.get("INIT").name == self.fsm._states.get("INIT").name, \
+ 'FSM underlying dictionary differ from original to pickled/reformed one'
+ assert loaded_fsm._states.get("Second").name == self.fsm._states.get("Second").name, \
+ 'FSM underlying dictionary differ from original to pickled/reformed one'
+ assert loaded_fsm._states.get("INIT").get_action_list()[0].message.value == \
+ self.fsm._states.get("INIT").get_action_list()[0].message.value, \
+ 'FSM underlying State underlying Action differ from original to reformed one'
+ assert len(loaded_fsm.get_action_list()) == 0, "FSM should not have any actions on itself"
+
+ def test_all_actions(self):
+ """
+ Inserts all the known action types in a FSM, then attempt to load it.
+ """
+ st = State("INIT")
+
+ act1 = BubbleMessage("Hi!", pos=[10,120], tailpos=[-12,30])
+ act2 = DialogMessage("Hello again.", pos=[120,10])
+ act3 = WidgetIdentifyAction()
+ act4 = DisableWidgetAction("0.0.0.1.0.0.0")
+ act5 = TypeTextAction("0.0.0.1.1.1.0.0", "New text")
+ act6 = ClickAction("0.0.1.0.1.1")
+ act7 = OnceWrapper(act1)
+ act8 = ChainAction([act1, act2, act3, act4])
+ actions = [act1, act2, act3, act4, act5, act6, act7, act8]
+
+ for action in actions:
+ st.add_action(action)
+
+ self.fsm.remove_state("Second")
+ self.fsm.remove_state("INIT")
+ self.fsm.add_state(st)
+
+ xml_ser = XMLSerializer()
+
+ self.test_save()
+
+ reloaded_fsm = xml_ser.load_fsm(str(self.uuid))
+
+ def test_all_filters(self):
+ """
+ Inserts all the known action types in a FSM, then attempt to load it.
+ """
+ st = State("INIT")
+
+ ev1 = TimerEvent("Second", 1000)
+ ev2 = GtkWidgetEventFilter("Second", "0.0.1.1.0.0.1", "clicked")
+ ev3 = GtkWidgetTypeFilter("Second", "0.0.1.1.1.2.3", text="Typed stuff")
+ ev4 = GtkWidgetTypeFilter("Second", "0.0.1.1.1.2.3", strokes="acbd")
+ filters = [ev1, ev2, ev3, ev4]
+
+ for filter in filters:
+ st.add_event_filter(filter)
+
+ self.fsm.remove_state("INIT")
+ self.fsm.add_state(st)
+
+ xml_ser = XMLSerializer()
+
+ self.test_save()
+
+ reloaded_fsm = xml_ser.load_fsm(str(self.uuid))
+
+if __name__ == "__main__":
+ unittest.main()