Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authormike <michael.jmontcalm@gmail.com>2009-10-19 04:38:32 (GMT)
committer mike <michael.jmontcalm@gmail.com>2009-10-19 04:38:32 (GMT)
commit6584510d390a37153c20974da6704a907058fea0 (patch)
treea0649a77b36b63885774e0af25ec752192a5c404 /tests
parent2aef185e57f6c6c38670a5eea74f7889b3d56944 (diff)
parent3b9bff2ef1826987d95815ff03c235052cea9aae (diff)
Merge gitorious@git.sugarlabs.org:tutorius/michaeljm-dev into merge_michaeljm-dev
Diffstat (limited to 'tests')
-rw-r--r--tests/actiontests.py169
-rw-r--r--tests/addontests.py50
-rw-r--r--tests/bundlertests.py77
-rw-r--r--tests/constraintstests.py15
-rw-r--r--tests/coretests.py412
-rw-r--r--tests/filterstests.py6
-rw-r--r--tests/linear_creatortests.py2
-rw-r--r--tests/propertiestests.py190
-rwxr-xr-xtests/run-tests.py74
-rw-r--r--tests/serializertests.py33
-rw-r--r--tests/storetests.py107
11 files changed, 836 insertions, 299 deletions
diff --git a/tests/actiontests.py b/tests/actiontests.py
index 4e126b3..7b8d1cb 100644
--- a/tests/actiontests.py
+++ b/tests/actiontests.py
@@ -25,6 +25,7 @@ import unittest
import gtk
from sugar.tutorius import addon
+from sugar.tutorius.addons.triggereventfilter import *
from sugar.tutorius.actions import *
from sugar.tutorius.services import ObjectStore
@@ -65,7 +66,7 @@ class DialogMessageTest(unittest.TestCase):
class BubbleMessageTest(unittest.TestCase):
def setUp(self):
- self.bubble = addon.create('BubbleMessage', message="Message text", pos=[200, 300], tailpos=[-15, -25])
+ self.bubble = addon.create('BubbleMessage', message="Message text", position=[200, 300], tail_pos=[-15, -25])
def test_properties(self):
props = self.bubble.get_properties()
@@ -115,7 +116,7 @@ class OnceWrapperTests(unittest.TestCase):
CountAction
"""
act = CountAction()
- wrap = OnceWrapper(act)
+ wrap = addon.create('OnceWrapper', act)
assert act.do_count == 0, "do() should not have been called in __init__()"
assert act.undo_count == 0, "undo() should not have been called in __init__()"
@@ -152,7 +153,7 @@ class ChainActionTest(unittest.TestCase):
def test_empty(self):
"""If the expected empty behavior (do nothing) changes
and starts throwing exceptions, this will flag it"""
- a = ChainAction()
+ a = addon.create('ChainAction')
a.do()
a.undo()
@@ -161,7 +162,7 @@ class ChainActionTest(unittest.TestCase):
first = ChainTester(witness)
second = ChainTester(witness)
- c = ChainAction(first, second)
+ c = addon.create('ChainAction', [first, second])
assert witness == [], "Actions should not be triggered on init"""
c.do()
@@ -194,13 +195,171 @@ class DisableWidgetActionTests(unittest.TestCase):
assert btn.props.sensitive is True, "Callback should have been called"
- act = DisableWidgetAction("0")
+ act = addon.create('DisableWidgetAction', "0")
assert btn.props.sensitive is True, "Callback should have been called again"
act.do()
assert btn.props.sensitive is False, "Callback should not have been called again"
act.undo()
assert btn.props.sensitive is True, "Callback should have been called again"
+class TrueWhileActiveAction(Action):
+ """
+ This action's active member is set to True after a do and to False after
+ an undo.
+
+ Used to verify that a State correctly triggers the do and undo actions.
+ """
+ def __init__(self):
+ Action.__init__(self)
+ self.active = False
+
+ def do(self):
+ self.active = True
+
+ def undo(self):
+ self.active = False
+
+class ClickableWidget():
+ """
+ This class fakes a widget with a clicked() method
+ """
+ def __init__(self):
+ self.click_count = 0
+
+ def clicked(self):
+ self.click_count += 1
+
+class FakeTextEntry():
+ """
+ This class fakes a widget with an insert_text() method
+ """
+ def __init__(self):
+ self.text_lines = []
+ self.last_entered_line = ""
+ self.displayed_text = ""
+
+ def insert_text(self, text, index):
+ self.last_entered_line = text
+ self.text_lines.append(text)
+ self.displayed_text = self.displayed_text[0:index] + text + self.displayed_text[index+1:]
+
+class FakeParentWidget():
+ """
+ This class fakes a widet container, it implements the get_children() method
+ """
+ def __init__(self):
+ self._children = []
+
+ def add_child(self, child):
+ self._children.append(child)
+
+ def get_children(self):
+ return self._children
+
+class FakeEventFilter(TriggerEventFilter):
+ """
+ This is a fake event that is connected to the tutorial.
+
+ The difference between this one and the TriggerEventFilter is that the
+ tutorial's set_state will be called on the callback.
+
+ Do not forget to add the do_callback() after creating the object.
+ """
+ def set_tutorial(self, tutorial):
+ self.tutorial = tutorial
+
+ def _inner_cb(self, event_filter):
+ self.toggle_on_callback = not self.toggle_on_callback
+ self.tutorial.set_state(event_filter.get_next_state())
+
+class TypeTextActionTests(unittest.TestCase):
+ """
+ Test class for type text action
+ """
+ def test_do_action(self):
+ activity = FakeParentWidget()
+ widget = FakeTextEntry()
+ activity.add_child(widget)
+ ObjectStore().activity = activity
+
+ test_text = "This is text"
+
+
+ action = addon.create('TypeTextAction', "0.0", test_text)
+
+ assert widget == ObjectStore().activity.get_children()[0],\
+ "The clickable widget isn't reachable from the object store \
+ the test cannot pass"
+
+ action.do()
+
+ assert widget.last_entered_line == test_text, "insert_text() should have been called by do()"
+
+ action.do()
+
+ assert widget.last_entered_line == test_text, "insert_text() should have been called by do()"
+ assert len(widget.text_lines) == 2, "insert_text() should have been called twice"
+
+ def test_undo(self):
+ activity = FakeParentWidget()
+ widget = FakeTextEntry()
+ activity.add_child(widget)
+ ObjectStore().activity = activity
+
+ test_text = "This is text"
+
+
+ action = addon.create('TypeTextAction', "0.0", test_text)
+
+ assert widget == ObjectStore().activity.get_children()[0],\
+ "The clickable widget isn't reachable from the object store \
+ the test cannot pass"
+
+ action.undo()
+
+ #There is no undo for this action so the test should not fail
+ assert True
+
+class ClickActionTests(unittest.TestCase):
+ """
+ Test class for click action
+ """
+ def test_do_action(self):
+ activity = FakeParentWidget()
+ widget = ClickableWidget()
+ activity.add_child(widget)
+ ObjectStore().activity = activity
+
+ action = addon.create('ClickAction', "0.0")
+
+ assert widget == ObjectStore().activity.get_children()[0],\
+ "The clickable widget isn't reachable from the object store \
+ the test cannot pass"
+
+ action.do()
+
+ assert widget.click_count == 1, "clicked() should have been called by do()"
+
+ action.do()
+
+ assert widget.click_count == 2, "clicked() should have been called by do()"
+
+ def test_undo(self):
+ activity = FakeParentWidget()
+ widget = ClickableWidget()
+ activity.add_child(widget)
+ ObjectStore().activity = activity
+
+ action = addon.create('ClickAction', "0.0")
+
+ assert widget == ObjectStore().activity.get_children()[0],\
+ "The clickable widget isn't reachable from the object store \
+ the test cannot pass"
+
+ action.undo()
+
+ #There is no undo for this action so the test should not fail
+ assert True
if __name__ == "__main__":
unittest.main()
diff --git a/tests/addontests.py b/tests/addontests.py
new file mode 100644
index 0000000..5fb4f61
--- /dev/null
+++ b/tests/addontests.py
@@ -0,0 +1,50 @@
+# Copyright (C) 2009, Tutorius.org
+# Copyright (C) 2009, Simon Poirier <simpoir@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
+
+import unittest
+
+from sugar.tutorius import addon
+
+class AddonTest(unittest.TestCase):
+ def test_create_constructor_fail(self):
+ try:
+ obj = addon.create("BubbleMessage", wrong_param=True, second_wrong="This", last_wrong=12, unknown=13.4)
+ assert False, "Constructor with wrong parameter should raise an exception"
+ except:
+ pass
+
+ def test_create_wrong_addon(self):
+ try:
+ obj = addon.create("Non existing addon name")
+ assert False, "Addon creator should raise an exception when the requested addon is unknown"
+ except:
+ pass
+
+ def test_create(self):
+ obj = addon.create("BubbleMessage", message="Hi!", position=[12,31])
+
+ assert obj is not None
+
+ def test_reload_addons(self):
+ addon._cache = None
+ assert len(addon.list_addons()) > 0, "Addons should be reloaded upon cache clear"
+
+ def test_get_addon_meta(self):
+ addon._cache = None
+ meta = addon.get_addon_meta("BubbleMessage")
+ assert meta.keys() == ['mandatory_props', 'class', 'display_name', 'name', 'icon',]
diff --git a/tests/bundlertests.py b/tests/bundlertests.py
index 8da2310..ad8d1bb 100644
--- a/tests/bundlertests.py
+++ b/tests/bundlertests.py
@@ -26,7 +26,76 @@ import unittest
import os
import uuid
-from sugar.tutorius import bundler
+from sugar.tutorius import bundler
+
+##class VaultTests(unittest.TestCase):
+## def setUp(self):
+## pass
+##
+## def tearDown(self):
+## pass
+##
+## def test_basicQuery(self):
+## vault = Vault()
+##
+## list_metadata = vault.query(keyword='tutorial', startIndex=2, numResults=5)
+##
+## assert len(list_metadata) <= 5
+##
+## def test_advancedQuery(self):
+## vault = Vault()
+##
+## list_metadata = vault.query(keyword='', category='Math', startIndex=10, numResults=10)
+##
+## assert len(list_metadata) <= 10
+##
+## pass
+##
+## def test_installTutorial(self):
+## # Create a new tutorial
+##
+##
+## xml_serializer = XmlSerializer()
+##
+##
+## xml_serializer.save_fsm()
+##
+## def test_deleteTutorial(self):
+## pass
+##
+## def test_saveTutorial(self):
+## pass
+##
+## def test_readTutorial(self):
+## pass
+##
+## def _generateSampleTutorial(self):
+## """
+## Creates a new tutorial and bundles it.
+##
+## @return The UUID for the new tutorial.
+## """
+## self._fsm = FiniteStateMachine("Sample testing FSM")
+## # Add a few states
+## act1 = addon.create('BubbleMessage', message="Hi", pos=[300, 450])
+## ev1 = addon.create('GtkWidgetEventFilter', "0.12.31.2.2", "clicked", "FINAL")
+## act2 = addon.create('BubbleMessage', message="Second message", pos=[250, 150], tailpos=[1,2])
+##
+## st1 = State("INIT")
+## st1.add_action(act1)
+## st1.add_event_filter(ev1)
+##
+## st2 = State("FINAL")
+## st2.add_action(act2)
+##
+## self._fsm.add_state(st1)
+## self._fsm.add_state(st2)
+##
+## xml_ser = XmlSerializer()
+##
+## os.makedirs(os.path.join(sugar.tutorius.bundler._get_store_root(), str(self.uuid)))
+##
+## # xml_ser.save_fsm(self._fsm, TUTORIAL_FILENAME,
class TutorialBundlerTests(unittest.TestCase):
@@ -51,15 +120,15 @@ class TutorialBundlerTests(unittest.TestCase):
os.rmdir(self.guid_path)
def test_add_ressource(self):
- bund = bundler.TutorialBundler(self.test_guid)
+ bund = bundler.TutorialBundler(unicode(self.test_guid))
temp_file = open("test.txt",'w')
temp_file.write('test')
temp_file.close()
- bund.add_resource("test.txt")
+ bund.add_resources("text", "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
+ unittest.main()
diff --git a/tests/constraintstests.py b/tests/constraintstests.py
index b7b0a47..4e19a92 100644
--- a/tests/constraintstests.py
+++ b/tests/constraintstests.py
@@ -16,6 +16,9 @@
import unittest
+import uuid
+import os
+
from sugar.tutorius.constraints import *
class ConstraintTest(unittest.TestCase):
@@ -218,10 +221,18 @@ class EnumConstraintTest(unittest.TestCase):
assert False, "Wrong exception type thrown"
class FileConstraintTest(unittest.TestCase):
+ def setUp(self):
+ self.temp_filename = "sample_file_" + str(uuid.uuid1()) + ".txt"
+ self.file1 = file(self.temp_filename, "w")
+ self.file1.close()
+
+ def tearDown(self):
+ os.unlink(self.temp_filename)
+
def test_validate(self):
cons = FileConstraint()
- cons.validate("run-tests.py")
+ cons.validate(self.temp_filename)
try:
cons.validate("unknown/file.py")
@@ -230,4 +241,4 @@ class FileConstraintTest(unittest.TestCase):
pass
if __name__ == "__main__":
- unittest.main() \ No newline at end of file
+ unittest.main()
diff --git a/tests/coretests.py b/tests/coretests.py
index eadea01..4f564c8 100644
--- a/tests/coretests.py
+++ b/tests/coretests.py
@@ -28,13 +28,14 @@ and event filters. Those are in their separate test module
import unittest
+import copy
import logging
-from sugar.tutorius.actions import Action, OnceWrapper, ClickAction, TypeTextAction
+from sugar.tutorius.actions import *
+from sugar.tutorius.addon import *
from sugar.tutorius.core import *
from sugar.tutorius.filters import *
-
-from actiontests import CountAction
+from actiontests import CountAction, FakeEventFilter
# Helper classes to help testing
class SimpleTutorial(Tutorial):
@@ -49,6 +50,28 @@ class SimpleTutorial(Tutorial):
def set_state(self, name):
self.current_state_name = name
+class TutorialTest(unittest.TestCase):
+ """Tests the tutorial functions that are not covered elsewhere."""
+ def test_detach(self):
+ class Activity(object):
+ name = "this"
+
+ activity1 = Activity()
+ activity2 = Activity()
+
+ fsm = FiniteStateMachine("Sample example")
+
+ tutorial = Tutorial("Test tutorial", fsm)
+
+ assert tutorial.activity == None, "There is a default activity in the tutorial"
+
+ tutorial.attach(activity1)
+
+ assert tutorial.activity == activity1, "Activity should have been associated to this tutorial"
+
+ tutorial.attach(activity2)
+ assert tutorial.activity == activity2, "Activity should have been changed to activity2"
+
class TutorialWithFSM(Tutorial):
"""
Fake tutorial, but associated with a FSM.
@@ -73,173 +96,6 @@ class TrueWhileActiveAction(Action):
def undo(self):
self.active = False
-
-class ClickableWidget():
- """
- This class fakes a widget with a clicked() method
- """
- def __init__(self):
- self.click_count = 0
-
- def clicked(self):
- self.click_count += 1
-
-class FakeTextEntry():
- """
- This class fakes a widget with an insert_text() method
- """
- def __init__(self):
- self.text_lines = []
- self.last_entered_line = ""
- self.displayed_text = ""
-
- def insert_text(self, text, index):
- self.last_entered_line = text
- self.text_lines.append(text)
- self.displayed_text = self.displayed_text[0:index] + text + self.displayed_text[index+1:]
-
-class FakeParentWidget():
- """
- This class fakes a widet container, it implements the get_children() method
- """
- def __init__(self):
- self._children = []
-
- def add_child(self, child):
- self._children.append(child)
-
- def get_children(self):
- return self._children
-
-
-
-
-class TriggerEventFilter(EventFilter):
- """
- This event filter can be triggered by simply calling its do_callback function.
-
- Used to fake events and see the effect on the FSM.
- """
- def __init__(self, next_state):
- EventFilter.__init__(self, next_state)
- self.toggle_on_callback = False
-
- def install_handlers(self, callback, **kwargs):
- """
- Forsakes the incoming callback function and just set the inner one.
- """
- self._callback = self._inner_cb
-
- def _inner_cb(self, event_filter):
- self.toggle_on_callback = not self.toggle_on_callback
-
-class FakeEventFilter(TriggerEventFilter):
- """
- This is a fake event that is connected to the tutorial.
-
- The difference between this one and the TriggerEventFilter is that the
- tutorial's set_state will be called on the callback.
-
- Do not forget to add the do_callback() after creating the object.
- """
- def set_tutorial(self, tutorial):
- self.tutorial = tutorial
-
- def _inner_cb(self, event_filter):
- self.toggle_on_callback = not self.toggle_on_callback
- self.tutorial.set_state(event_filter.get_next_state())
-
-
-class ClickActionTests(unittest.TestCase):
- """
- Test class for click action
- """
- def test_do_action(self):
- activity = FakeParentWidget()
- widget = ClickableWidget()
- activity.add_child(widget)
- ObjectStore().activity = activity
-
- action = ClickAction("0.0")
-
- assert widget == ObjectStore().activity.get_children()[0],\
- "The clickable widget isn't reachable from the object store \
- the test cannot pass"
-
- action.do()
-
- assert widget.click_count == 1, "clicked() should have been called by do()"
-
- action.do()
-
- assert widget.click_count == 2, "clicked() should have been called by do()"
-
- def test_undo(self):
- activity = FakeParentWidget()
- widget = ClickableWidget()
- activity.add_child(widget)
- ObjectStore().activity = activity
-
- action = ClickAction("0.0")
-
- assert widget == ObjectStore().activity.get_children()[0],\
- "The clickable widget isn't reachable from the object store \
- the test cannot pass"
-
- action.undo()
-
- #There is no undo for this action so the test should not fail
- assert True
-
-
-
-class TypeTextActionTests(unittest.TestCase):
- """
- Test class for type text action
- """
- def test_do_action(self):
- activity = FakeParentWidget()
- widget = FakeTextEntry()
- activity.add_child(widget)
- ObjectStore().activity = activity
-
- test_text = "This is text"
-
-
- action = TypeTextAction("0.0", test_text)
-
- assert widget == ObjectStore().activity.get_children()[0],\
- "The clickable widget isn't reachable from the object store \
- the test cannot pass"
-
- action.do()
-
- assert widget.last_entered_line == test_text, "insert_text() should have been called by do()"
-
- action.do()
-
- assert widget.last_entered_line == test_text, "insert_text() should have been called by do()"
- assert len(widget.text_lines) == 2, "insert_text() should have been called twice"
-
- def test_undo(self):
- activity = FakeParentWidget()
- widget = FakeTextEntry()
- activity.add_child(widget)
- ObjectStore().activity = activity
-
- test_text = "This is text"
-
-
- action = TypeTextAction("0.0", test_text)
-
- assert widget == ObjectStore().activity.get_children()[0],\
- "The clickable widget isn't reachable from the object store \
- the test cannot pass"
-
- action.undo()
-
- #There is no undo for this action so the test should not fail
- assert True
# State testing class
class StateTest(unittest.TestCase):
@@ -274,7 +130,7 @@ class StateTest(unittest.TestCase):
Tests the fact that the event filters are correctly installed on setup
and uninstalled on teardown.
"""
- event_filter = TriggerEventFilter("second_state")
+ event_filter = addon.create('TriggerEventFilter', "second_state")
state = State("event_test", event_filter_list=[event_filter])
state.set_tutorial(SimpleTutorial())
@@ -326,14 +182,11 @@ class StateTest(unittest.TestCase):
assert state.add_action(act2), "Could not add the second action"
assert state.add_action(act3), "Could not add the third action"
- # Try to add a second time an action that was already inserted
- assert state.add_action(act1) == False, "Not supposed to insert an action twice"
-
# Fetch the associated actions
actions = state.get_action_list()
# Make sure all the actions are present in the state
- assert act1 in actions and act2 in actions and act3 in actions,\
+ assert act1 in actions and act2 in actions and act3 in actions, \
"The actions were not properly inserted in the state"
# Clear the list
@@ -345,9 +198,9 @@ class StateTest(unittest.TestCase):
def test_add_event_filter(self):
state = State("INIT")
- event1 = TriggerEventFilter("s")
- event2 = TriggerEventFilter("t")
- event3 = TriggerEventFilter("r")
+ event1 = addon.create('TriggerEventFilter', "s")
+ event2 = addon.create('TriggerEventFilter', "t")
+ event3 = addon.create('TriggerEventFilter', "r")
# Insert the event filters
assert state.add_event_filter(event1), "Could not add event filter 1"
@@ -368,7 +221,80 @@ class StateTest(unittest.TestCase):
assert len(state.get_event_filter_list()) == 0, \
"Could not clear the event filter list properly"
+
+ def test_eq_simple(self):
+ """
+ Two empty states with the same name must be identical
+ """
+ st1 = State("Identical")
+ st2 = State("Identical")
+
+ assert st1 == st2, "Empty states with the same name should be identical"
+
+ def test_eq(self):
+ """
+ Test whether two states share the same set of actions and event filters.
+ """
+ st1 = State("Identical")
+ st2 = State("Identical")
+
+ non_state = object()
+
+ act1 = addon.create("BubbleMessage", message="Hi", position=[132,450])
+ act2 = addon.create("BubbleMessage", message="Hi", position=[132,450])
+
+ event1 = addon.create("GtkWidgetEventFilter", "nextState", "0.0.0.1.1.2.3.1", "clicked")
+
+ act3 = addon.create("DialogMessage", message="Hello again.", position=[200, 400])
+
+ # Build the first state
+ st1.add_action(act1)
+ st1.add_action(act3)
+ st1.add_event_filter(event1)
+
+ # Build the second state
+ st2.add_action(act2)
+ st2.add_action(act3)
+ st2.add_event_filter(event1)
+
+ # Make sure that they are identical for now
+ assert st1 == st2, "States should be considered as identical"
+ assert st2 == st1, "States should be considered as identical"
+ # Modify the second bubble message action
+ act2.message = "New message"
+
+ # Since one action changed in the second state, this should indicate that the states
+ # are not identical anymore
+ assert not (st1 == st2), "Action was changed and states should be different"
+ assert not (st2 == st1), "Action was changed and states should be different"
+
+ # Make sure that trying to find identity with something else than a State object fails properly
+ assert not (st1 == non_state), "Passing a non-State object should fail for identity"
+
+ st2.name = "Not identical anymore"
+ assert not(st1 == st2), "Different state names should give different states"
+ st2.name = "Identical"
+
+ st3 = copy.deepcopy(st1)
+ st3.add_action(addon.create("BubbleMessage", "Hi!", [128,264]))
+
+ assert not (st1 == st3), "States having a different number of actions should be different"
+
+ st4 = copy.deepcopy(st1)
+ st4.add_event_filter(addon.create("GtkWidgetEventFilter", "next_state", "0.0.1.1.2.2.3", "clicked"))
+
+ assert not (st1 == st4), "States having a different number of events should be different"
+
+ st5 = copy.deepcopy(st1)
+ st5._event_filters = []
+
+ st5.add_event_filter(addon.create("GtkWidgetEventFilter", "other_state", "0.1.2.3.4.1.2", "pressed"))
+
+ #import rpdb2; rpdb2.start_embedded_debugger('pass')
+ assert not (st1 == st5), "States having the same number of event filters" \
+ + " but those being different should be different"
+
class FSMTest(unittest.TestCase):
"""
This class needs to text the interface and functionality of the Finite
@@ -413,6 +339,7 @@ class FSMTest(unittest.TestCase):
assert act_second.active == False, "FSM did not teardown SECOND properly"
+
def test_state_insert(self):
"""
This is a simple test to insert, then find a state.
@@ -472,9 +399,9 @@ class FSMTest(unittest.TestCase):
This test removes a state from the FSM. It also verifies that the links
from other states going into the removed state are gone.
"""
- st1 = State("INIT", event_filter_list=[TriggerEventFilter("second")])
- st2 = State("second", event_filter_list=[TriggerEventFilter("third")])
- st3 = State("third", event_filter_list=[TriggerEventFilter("second")])
+ st1 = State("INIT", event_filter_list=[addon.create('TriggerEventFilter', "second")])
+ st2 = State("second", event_filter_list=[addon.create('TriggerEventFilter', "third")])
+ st3 = State("third", event_filter_list=[addon.create('TriggerEventFilter', "second")])
fsm = FiniteStateMachine("StateRemovalTest")
@@ -504,10 +431,10 @@ class FSMTest(unittest.TestCase):
# Make sure that there is no link to the removed state in the rest
# of the FSM
- assert "second" not in fsm.get_following_states("INIT"),\
+ assert "second" not in fsm.get_following_states("INIT"), \
"The link to second from INIT still exists after removal"
- assert "second" not in fsm.get_following_states("third"),\
+ 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):
@@ -534,8 +461,116 @@ class FSMTest(unittest.TestCase):
"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,\
+ 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
+
+ def test_setup(self):
+ fsm = FiniteStateMachine("New state machine")
+
+ try:
+ fsm.setup()
+ assert False, "fsm should throw an exception when trying to setup and not bound to a tutorial"
+ except UnboundLocalError:
+ pass
+
+ def test_setup_actions(self):
+ tut = SimpleTutorial()
+
+ states_dict = {"INIT": State("INIT")}
+ fsm = FiniteStateMachine("New FSM", state_dict=states_dict)
+
+ act = CountAction()
+ fsm.add_action(act)
+
+ fsm.set_tutorial(tut)
+
+ fsm.setup()
+
+ # Let's also test the current state name
+ assert fsm.get_current_state_name() == "INIT", "Initial state should be INIT"
+
+ assert act.do_count == 1, "Action should have been called during setup"
+
+ fsm._fsm_has_finished = True
+
+ fsm.teardown()
+
+ assert act.undo_count == 1, "Action should have been undone"
+
+ def test_string_rep(self):
+ fsm = FiniteStateMachine("Testing machine")
+
+ st1 = State("INIT")
+ st2 = State("Other State")
+ st3 = State("Final State")
+
+ st1.add_action(addon.create("BubbleMessage", "Hi!", [132,312]))
+
+ fsm.add_state(st1)
+ fsm.add_state(st2)
+ fsm.add_state(st3)
+
+ assert str(fsm) == "INIT, Final State, Other State, "
+
+ def test_eq_(self):
+ fsm = FiniteStateMachine("Identity test")
+
+ non_fsm_object = object()
+
+ assert not (fsm == non_fsm_object), "Testing with non FSM object should not give identity"
+
+ # Compare FSMs
+ act1 = CountAction()
+
+ fsm.add_action(act1)
+
+ fsm2 = copy.deepcopy(fsm)
+
+ assert fsm == fsm2
+
+ act2 = CountAction()
+ fsm2.add_action(act2)
+
+ assert not(fsm == fsm2), \
+ "FSMs having a different number of actions should be different"
+
+ fsm3 = FiniteStateMachine("Identity test")
+
+ act3 = addon.create("BubbleMessage", "Hi!", [123,312])
+ fsm3.add_action(act3)
+
+ assert not(fsm3 == fsm), \
+ "Actions having the same number of actions but different ones should be different"
+
+ st1 = State("INIT")
+
+ st2 = State("OtherState")
+
+ fsm.add_state(st1)
+ fsm.add_state(st2)
+
+ fsm4 = copy.deepcopy(fsm)
+
+ assert fsm == fsm4
+
+ st3 = State("Last State")
+
+ fsm4.add_state(st3)
+
+ assert not (fsm == fsm4), "FSMs having a different number of states should not be identical"
+
+ fsm4.remove_state("OtherState")
+
+ assert not (fsm == fsm4), "FSMs having different states should be different"
+
+ fsm4.remove_state("Last State")
+
+ st5 = State("OtherState")
+ st5.add_action(CountAction())
+
+ fsm4.add_state(st5)
+
+ assert not(fsm == fsm4), "FSMs having states with same name but different content should be different"
class FSMExplorationTests(unittest.TestCase):
def setUp(self):
@@ -547,13 +582,13 @@ class FSMExplorationTests(unittest.TestCase):
"""
st1 = State("INIT")
st1.add_action(CountAction())
- st1.add_event_filter(TriggerEventFilter("Second"))
- st1.add_event_filter(TriggerEventFilter("Third"))
+ st1.add_event_filter(addon.create('TriggerEventFilter', "Second"))
+ st1.add_event_filter(addon.create('TriggerEventFilter', "Third"))
st2 = State("Second")
st2.add_action(TrueWhileActiveAction())
- st2.add_event_filter(TriggerEventFilter("Third"))
- st2.add_event_filter(TriggerEventFilter("Fourth"))
+ st2.add_event_filter(addon.create('TriggerEventFilter', "Third"))
+ st2.add_event_filter(addon.create('TriggerEventFilter', "Fourth"))
st3 = State("Third")
st3.add_action(CountAction())
@@ -592,6 +627,5 @@ class FSMExplorationTests(unittest.TestCase):
self.validate_previous_states("Fourth", ("Second"))
-
if __name__ == "__main__":
unittest.main()
diff --git a/tests/filterstests.py b/tests/filterstests.py
index 3e79bcc..c45f924 100644
--- a/tests/filterstests.py
+++ b/tests/filterstests.py
@@ -26,7 +26,7 @@ import time
import gobject
import gtk
-from sugar.tutorius.filters import EventFilter, TimerEvent, GtkWidgetTypeFilter
+from sugar.tutorius.filters import EventFilter
from sugar.tutorius import addon
from gtkutilstests import SignalCatcher
@@ -79,7 +79,7 @@ class TestTimerEvent(unittest.TestCase):
ctx = gobject.MainContext()
main = gobject.MainLoop(ctx)
- e = TimerEvent("Next",1) #1 second should be enough :s
+ e = addon.create('TimerEvent', "Next", 2) # 2 seconds should be enough :s
s = SignalCatcher()
e.install_handlers(s.callback)
@@ -122,7 +122,7 @@ class TestTimerEvent(unittest.TestCase):
ctx = gobject.MainContext()
main = gobject.MainLoop(ctx)
- e = TimerEvent("Next",1) #1 second should be enough :s
+ e = addon.create('TimerEvent', "Next", 2) # 2 seconds should be enough :s
s = SignalCatcher()
e.install_handlers(s.callback)
diff --git a/tests/linear_creatortests.py b/tests/linear_creatortests.py
index dcded57..999f4d5 100644
--- a/tests/linear_creatortests.py
+++ b/tests/linear_creatortests.py
@@ -19,7 +19,7 @@ from sugar.tutorius.core import *
from sugar.tutorius.actions import *
from sugar.tutorius.filters import *
from sugar.tutorius.linear_creator import *
-from coretests import TriggerEventFilter
+from sugar.tutorius.addons.triggereventfilter import *
from actiontests import CountAction
import unittest
diff --git a/tests/propertiestests.py b/tests/propertiestests.py
index 46346c4..0b8251a 100644
--- a/tests/propertiestests.py
+++ b/tests/propertiestests.py
@@ -15,6 +15,9 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import unittest
+import uuid
+import os
+import copy
from sugar.tutorius.constraints import *
from sugar.tutorius.properties import *
@@ -81,7 +84,128 @@ class BasePropertyTest(unittest.TestCase):
obj.prop = 2
assert obj.prop == 2, "Unable to set a value on base class"
+
+ def test_eq_(self):
+ class klass(TPropContainer):
+ prop = TutoriusProperty()
+ obj = klass()
+
+ obj2 = klass()
+
+ assert obj == obj2, "Base property containers should be identical"
+class AdvancedPropertyTest(unittest.TestCase):
+ def test_properties_groups(self):
+ """
+ Tests complex properties containers for identity.
+ """
+
+ class klass1(TPropContainer):
+ message = TutoriusProperty()
+ property = TutoriusProperty()
+ data = TutoriusProperty()
+
+ class klass3(TPropContainer):
+ property = TutoriusProperty()
+ message = TutoriusProperty()
+ data = TutoriusProperty()
+ extra_prop = TutoriusProperty()
+
+ class klass4(TPropContainer):
+ property = TutoriusProperty()
+ message = TutoriusProperty()
+ data = TFloatProperty(13.0)
+
+ obj1 = klass1()
+ obj1.property = 12
+ obj1.message = "Initial message"
+ obj1.data = [132, 208, 193, 142]
+
+ obj2 = klass1()
+ obj2.property = 12
+ obj2.message = "Initial message"
+ obj2.data = [132, 208, 193, 142]
+
+ obj3 = klass3()
+ obj3.property = 12
+ obj3.message = "Initial message"
+ obj3.data = [132, 208, 193, 142]
+ obj3.extra_prop = "Suprprise!"
+
+ obj4 = klass4()
+ obj4.property = 12
+ obj4.message = "Initial message"
+ obj4.data = 13.4
+
+ # Ensure that both obj1 and obj2 are identical (they have the same list of
+ # properties and they have the same values
+ assert obj1 == obj1, "Identical objects were considered as different"
+
+ # Ensure that obj1 is different from obj3, since obj3 has an extra property
+ assert not (obj1 == obj3), "Objects should not be identical since obj3 has more props"
+ assert not (obj3 == obj1), "Objects should not be identical since obj3 has more properties"
+
+ # Ensure that properties of different type are considered as different
+ assert not (obj1 == obj4), "Properties of different type should not be equal"
+
+ def test_addon_properties(self):
+ """Test an addon property.
+
+ This tests creates a class with a single addon property (klass1) and
+ assigns a new addon to it (inner1)."""
+ class klass1(TPropContainer):
+ addon = TAddonProperty()
+
+ class inner1(TPropContainer):
+ internal = TutoriusProperty()
+ def __init__(self, value):
+ TPropContainer.__init__(self)
+ self.internal = value
+
+ obj1 = klass1()
+ obj1.addon = inner1("Hi!")
+
+ obj2 = klass1()
+ obj2.addon = inner1("Hi!")
+
+ assert obj1 == obj2, "Identical objects with addon properties were treated as different"
+
+ obj3 = klass1()
+ obj3.addon = inner1("Hello!")
+
+ assert not (obj1 == obj3), "Objects with addon property having a different value should be considered different"
+
+ def test_addonlist_properties(self):
+ class klass1(TPropContainer):
+ addon_list = TAddonListProperty()
+
+ class inner1(TPropContainer):
+ message = TutoriusProperty()
+ data = TutoriusProperty()
+ def __init__(self, message, data):
+ TPropContainer.__init__(self)
+ self.message = message
+ self.data = data
+
+ class inner2(TPropContainer):
+ message = TutoriusProperty()
+ other_data = TutoriusProperty()
+ def __init__(self, message, data):
+ TPropContainer.__init__(self)
+ self.message = message
+ self.other_data = data
+
+ obj1 = klass1()
+ obj1.addon_list = [inner1('Hi!', 12), inner1('Hello.', [1,2])]
+ obj2 = klass1()
+ obj2.addon_list = [inner1('Hi!', 12), inner1('Hello.', [1,2])]
+
+ assert obj1 == obj2, "Addon lists with the same containers were considered different"
+
+ obj3 = klass1()
+ obj3.addon_list = [inner1('Hi!', 12), inner2('Hello.', [1,2])]
+ assert not (obj1 == obj3), "Differently named properties should be considered different in the addon list tests"
+
class TIntPropertyTest(unittest.TestCase):
def test_int_property(self):
class klass(TPropContainer):
@@ -377,19 +501,38 @@ class TEnumPropertyTest(unittest.TestCase):
try_wrong_values(self.obj)
class TFilePropertyTest(unittest.TestCase):
+ root_folder = "/tmp/tutorius"
+
def setUp(self):
+ try:
+ os.mkdir(self.root_folder)
+ except:
+ pass
+ # Create some sample, unique files for the tests
+ self.temp_filename1 = os.path.join(self.root_folder, "sample_file1_" + str(uuid.uuid1()) + ".txt")
+ self.temp_file1 = file(self.temp_filename1, "w")
+ self.temp_file1.close()
+ self.temp_filename2 = os.path.join(self.root_folder, "sample_file2_" + str(uuid.uuid1()) + ".txt")
+ self.temp_file2 = file(self.temp_filename2, "w")
+ self.temp_file2.close()
+
class klass(TPropContainer):
- prop = TFileProperty("propertiestests.py")
+ prop = TFileProperty(self.temp_filename1)
self.obj = klass()
+
+ def tearDown(self):
+ # Unlink the files from the disk when tests are over
+ os.unlink(self.temp_filename1)
+ os.unlink(self.temp_filename2)
def test_basic_file(self):
- assert self.obj.prop == "propertiestests.py", "Could not set initial value"
+ assert self.obj.prop == self.temp_filename1, "Could not set initial value"
assert type(self.obj).prop.type == "file", "Wrong type for TFileProperty : %s"%type(self.obj).prop.type
- self.obj.prop = "run-tests.py"
+ self.obj.prop = self.temp_filename2
- assert self.obj.prop == "run-tests.py", "Could not change value"
+ assert self.obj.prop == self.temp_filename2, "Could not change value"
try:
self.obj.prop = "unknown/file/on/disk.gif"
@@ -397,6 +540,45 @@ class TFilePropertyTest(unittest.TestCase):
except FileConstraintError:
pass
+class TAddonPropertyTest(unittest.TestCase):
+ def test_wrong_value(self):
+ class klass1(TPropContainer):
+ addon = TAddonProperty()
+
+ class wrongAddon(object):
+ pass
+
+ obj1 = klass1()
+ obj1.addon = klass1()
+
+ try:
+ obj1.addon = wrongAddon()
+ assert False, "Addon Property should not accept non-TPropContainer values"
+ except ValueError:
+ pass
+
+class TAddonPropertyList(unittest.TestCase):
+ def test_wrong_value(self):
+ class klass1(TPropContainer):
+ addonlist = TAddonListProperty()
+
+ class wrongAddon(object):
+ pass
+
+ obj1 = klass1()
+
+ obj1.addonlist = [klass1(), klass1()]
+
+ try:
+ obj1.addonlist = klass1()
+ assert False, "TAddonPropeprty shouldn't accept anything else than a list"
+ except ValueError:
+ pass
+
+ try:
+ obj1.addonlist = [klass1(), klass1(), wrongAddon(), klass1()]
+ except ValueError:
+ pass
if __name__ == "__main__":
unittest.main()
diff --git a/tests/run-tests.py b/tests/run-tests.py
deleted file mode 100755
index d41aa0a..0000000
--- a/tests/run-tests.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/python
-# This is a dumb script to run tests on the sugar-jhbuild installed files
-# The path added is the default path for the jhbuild build
-
-INSTALL_PATH="../../../../../../install/lib/python2.5/site-packages/"
-
-import os, sys
-sys.path.insert(0,
- os.path.abspath(INSTALL_PATH)
-)
-
-FULL_PATH = os.path.join(INSTALL_PATH,"sugar/tutorius")
-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:
- ret += glob(os.path.join(FULL_PATH,dir,"*.py"))
- return ret
-
-import sys
-if __name__=='__main__':
- if "--coverage" in sys.argv:
- sys.argv=[arg for arg in sys.argv if arg != "--coverage"]
- import coverage
- coverage.erase()
- #coverage.exclude('raise NotImplementedError')
- coverage.start()
-
- import coretests
- import servicestests
- import gtkutilstests
- #import overlaytests # broken
- import linear_creatortests
- import actiontests
- import uamtests
- import filterstests
- import constraintstests
- import propertiestests
- import serializertests
- suite = unittest.TestSuite()
- suite.addTests(unittest.findTestCases(coretests))
- suite.addTests(unittest.findTestCases(servicestests))
- suite.addTests(unittest.findTestCases(gtkutilstests))
- #suite.addTests(unittest.findTestCases(overlaytests)) # broken
- suite.addTests(unittest.findTestCases(linear_creatortests))
- suite.addTests(unittest.findTestCases(actiontests))
- suite.addTests(unittest.findTestCases(uamtests))
- 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()
- else:
- from coretests import *
- from servicestests import *
- from gtkutilstests import *
- #from overlaytests import * # broken
- from actiontests import *
- from linear_creatortests import *
- from uamtests import *
- from filterstests import *
- from constraintstests import *
- from propertiestests import *
- from actiontests import *
- from serializertests import *
-
- unittest.main()
diff --git a/tests/serializertests.py b/tests/serializertests.py
index 6c25bae..2f2e287 100644
--- a/tests/serializertests.py
+++ b/tests/serializertests.py
@@ -74,9 +74,9 @@ class XMLSerializerTest(unittest.TestCase):
self.fsm = FiniteStateMachine("testingMachine")
# Add a few states
- act1 = addon.create('BubbleMessage', message="Hi", pos=[300, 450])
+ act1 = addon.create('BubbleMessage', message="Hi", position=[300, 450])
ev1 = addon.create('GtkWidgetEventFilter', "0.12.31.2.2", "clicked", "Second")
- act2 = addon.create('BubbleMessage', message="Second message", pos=[250, 150], tailpos=[1,2])
+ act2 = addon.create('BubbleMessage', message="Second message", position=[250, 150], tail_pos=[1,2])
st1 = State("INIT")
st1.add_action(act1)
@@ -107,11 +107,10 @@ class XMLSerializerTest(unittest.TestCase):
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
+ "Remove" boolean member specifies 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, bundler.TUTORIAL_FILENAME, os.path.join(sugar.tutorius.bundler._get_store_root(), str(self.uuid)))
def test_save_and_load(self):
@@ -143,14 +142,14 @@ class XMLSerializerTest(unittest.TestCase):
"""
st = State("INIT")
- act1 = addon.create('BubbleMessage', "Hi!", pos=[10,120], tailpos=[-12,30])
- act2 = addon.create('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])
+ act1 = addon.create('BubbleMessage', "Hi!", position=[10,120], tail_pos=[-12,30])
+ act2 = addon.create('DialogMessage', "Hello again.", position=[120,10])
+ act3 = addon.create('WidgetIdentifyAction')
+ act4 = addon.create('DisableWidgetAction', "0.0.0.1.0.0.0")
+ act5 = addon.create('TypeTextAction', "0.0.0.1.1.1.0.0", "New text")
+ act6 = addon.create('ClickAction', "0.0.1.0.1.1")
+ act7 = addon.create('OnceWrapper', action=act1)
+ act8 = addon.create('ChainAction', actions=[act1, act2, act3, act4])
actions = [act1, act2, act3, act4, act5, act6, act7, act8]
for action in actions:
@@ -163,7 +162,7 @@ class XMLSerializerTest(unittest.TestCase):
xml_ser = XMLSerializer()
self.test_save()
-
+
reloaded_fsm = xml_ser.load_fsm(str(self.uuid))
assert self.fsm == reloaded_fsm, "Expected equivalence before saving vs after loading."
@@ -173,10 +172,10 @@ class XMLSerializerTest(unittest.TestCase):
"""
st = State("INIT")
- ev1 = TimerEvent("Second", 1000)
- ev2 = addon.create('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")
+ ev1 = addon.create('TimerEvent', "Second", 1000)
+ ev2 = addon.create('GtkWidgetEventFilter', next_state="Second", object_id="0.0.1.1.0.0.1", event_name="clicked")
+ ev3 = addon.create('GtkWidgetTypeFilter', "Second", "0.0.1.1.1.2.3", text="Typed stuff")
+ ev4 = addon.create('GtkWidgetTypeFilter', "Second", "0.0.1.1.1.2.3", strokes="acbd")
filters = [ev1, ev2, ev3, ev4]
for filter in filters:
diff --git a/tests/storetests.py b/tests/storetests.py
new file mode 100644
index 0000000..da20c00
--- /dev/null
+++ b/tests/storetests.py
@@ -0,0 +1,107 @@
+# Copyright (C) 2009, Tutorius.org
+#
+# 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
+
+import unittest
+
+from sugar.tutorius.store import *
+
+g_tutorial_id = '114db454-b2a1-11de-8cfc-001f5bf747dc'
+g_other_id = '47efc6ee-b2a3-11de-8cfc-001f5bf747dc'
+
+class StoreProxyTest(unittest.TestCase):
+ def setUp(self):
+ self.store = StoreProxy()
+
+ def tearDown(self):
+ pass
+
+ def test_get_categories(self):
+ categories = self.store.get_categories()
+
+ assert isinstance(categories, list), "categories should be a list"
+
+ def test_get_tutorials(self):
+ self.store.get_tutorials()
+
+ def test_get_tutorial_collection(self):
+ collection_list = self.store.get_tutorial_collection('top5_rating')
+
+ assert isinstance(collection_list, list), "get_tutorial_collection should return a list"
+
+ def test_get_latest_version(self):
+ version_dict = self.store.get_latest_version([])
+
+ assert isinstance(version_dict, dict)
+
+ def test_download_tutorial(self):
+ tutorial = self.store.download_tutorial(g_tutorial_id)
+
+ assert tutorial is not None
+
+ def test_login(self):
+ assert self.store.login("unknown_user", "random_password")
+
+ def test_register_new_user(self):
+ user_info = {
+ 'name' : "Albert",
+ 'last_name' : "The Tester",
+ 'location' : 'Mozambique',
+ 'email' : 'albertthetester@mozambique.org'
+ }
+
+ assert self.store.register_new_user(user_info)
+
+
+class StoreProxyLoginTest(unittest.TestCase):
+ def setUp(self):
+ self.store = StoreProxy()
+ self.store.login("unknown_user", "random_password")
+
+ def tearDown(self):
+ session_id = self.store.get_session_id()
+
+ if session_id is not None:
+ self.store.close_session()
+
+ def test_close_session(self):
+ assert self.store.close_session()
+
+ def test_get_session_id(self):
+ session_id = self.store.get_session_id()
+
+ assert session_id is not None
+
+ def test_rate(self):
+ assert self.store.rate(5, g_tutorial_id)
+
+ def test_publish(self):
+ # TODO : We need to send in a real tutorial loaded from
+ # the Vault
+ assert self.store.publish(['This should be a real tutorial...'])
+
+ def test_unpublish(self):
+ # TODO : We need to send in a real tutorial loaded from
+ # the Vault
+ self.store.publish([g_tutorial_id, 'Fake tutorial'])
+
+ assert self.store.unpublish(g_tutorial_id)
+
+ def test_update_published_tutorial(self):
+ # TODO : Run these tests with files from the Vault
+ self.store.publish([g_tutorial_id, 'Fake tutorial'])
+
+ assert self.store.update_published_tutorial(g_tutorial_id, [g_tutorial_id, 'This is an updated tutorial'])
+