Merge lp:~jtatum/mago/gcalctool into lp:~mago-contributors/mago/mago-1.0

Proposed by James Tatum
Status: Merged
Merged at revision: not available
Proposed branch: lp:~jtatum/mago/gcalctool
Merge into: lp:~mago-contributors/mago/mago-1.0
Diff against target: None lines
To merge this branch: bzr merge lp:~jtatum/mago/gcalctool
Reviewer Review Type Date Requested Status
Ara Pulido Approve
Javier Collado (community) Approve
Review via email: mp+12236@code.launchpad.net

This proposal supersedes a proposal from 2009-09-11.

To post a comment you must log in.
Revision history for this message
James Tatum (jtatum) wrote : Posted in a previous version of this proposal

Adding tests for gcalctool

Revision history for this message
James Tatum (jtatum) wrote : Posted in a previous version of this proposal

Apologies to anyone who tried r115. There was a small typo in the suite code which broke most of the tests. Oops! r116 works properly.

Revision history for this message
Ara Pulido (ara) wrote : Posted in a previous version of this proposal

Hello James,

Excellent addition. I specially liked the way you solved the question of menus and buttons using lists.

Only a couple of comments:

In gcalctool_views.py and gcalctool_calculations.py you seemed to haved copypasted the skeleton from gedit_chains.py, and added an import (time, sfrtime...) not needed in these cases (minor issue, really).

Also, in gcalctool_views suite, you just check that the value has not changed. I don't think this is the correct thing to check. Indeed, it is also good to check that, it can be kept, but I would have also had checked things like:

* Buttons that only exist for that view, are now visible
* Window name has changed

Just some possible improvements to an overall very good job.

review: Needs Fixing
Revision history for this message
James Tatum (jtatum) wrote : Posted in a previous version of this proposal

Ara indicated there were superfluous imports in the tests which were removed. Also added tests for specific buttons on specific views. The way the Calculator class in mago/application/gnome.py is setup makes it very sensitive to the title bar, so it was not necessary to explicitly test for the correct title bar.

Revision history for this message
Ara Pulido (ara) wrote : Posted in a previous version of this proposal

It looks fine for me. Thanks for your changes!

I will wait for another person to approve, before merging.

review: Approve
Revision history for this message
Javier Collado (javier.collado) wrote : Posted in a previous version of this proposal

This is a good job, thanks James.

The tests worked perfectly in Karmic, but they didn't in Jaunty probably because LDTP version in repositories is a little old. However, I think this was useful to see that just setting the view to the expected value maybe isn't enough setup for a calculation test case.

For example, let's suppose that in a test case the '=' button wasn't correctly pressed, then the following test case needs to clear the display before continuing. Otherwise, the calculation doesn't start from scratch and the expected value won't be obtained. What do you think about this small change?

review: Needs Information
Revision history for this message
Javier Collado (javier.collado) wrote : Posted in a previous version of this proposal

Looking at gcalctools_views.xml, I saw that test cases are expected to be executed in the same order that they were written and that they are interrelated.

While this isn't necessarily bad, I'd say that it's a good practice to write test cases to be independently executed and that prerequisites should be part of test itself and not of a different test cases.

Do you agree on this?

review: Needs Information
Revision history for this message
James Tatum (jtatum) wrote :

Resubmitting. Javier correctly noted that the test cases did not need to depend on each other in gcalctool views. Updated.

Revision history for this message
Javier Collado (javier.collado) wrote :

Nice job.

review: Approve
Revision history for this message
Ara Pulido (ara) wrote :

Thanks James. Nice job.
I will merge your changes today.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'gcalctool'
=== added file 'gcalctool/README'
--- gcalctool/README 1970-01-01 00:00:00 +0000
+++ gcalctool/README 2009-09-11 02:51:23 +0000
@@ -0,0 +1,46 @@
1GCALCTOOL TESTS
2-----------
3Tests that verify calculator functionality.
4
5Safety
6------
7These tests will change the calculator's view, which is loaded at startup.
8Otherwise, they are safe to run.
9
10Configuration
11-------------
12No configuration is needed
13
14Version
15-------
16Tests were updated for Ubuntu Karmic
17
18Available Testsuites
19--------------------
20
21* gcalctool views (testcases wiki: cal-001)
22 Tools that exercise the views in gcalctool
23 These tests will also fail if the title bar text is incorrect
24 - Advanced
25 - Advanced button
26 Verify that the Square button exists in the current view
27 - Financial
28 - Financial button
29 Verify that the Future value button exists in the current view
30 - Scientific
31 - Scientific button
32 Verify that the ln button exists in the current view
33 - Programming
34 - Programming button
35 Verify that the 1's button exists in the current view
36 - Basic
37 - Basic button
38 Verify that the Reciprocal button is hidden in the current view
39* gcalctool calculations (testcases wiki: cal-002)
40 Tools that perform calculations in gcalctool and verify the results
41 - 3*4=12
42 - Square root 9=3
43 - 1+1=2
44 - 10-2=8
45 - 14/2=7
46 - 5*6=30
047
=== added file 'gcalctool/gcalctool_calculations.py'
--- gcalctool/gcalctool_calculations.py 1970-01-01 00:00:00 +0000
+++ gcalctool/gcalctool_calculations.py 2009-09-10 14:53:24 +0000
@@ -0,0 +1,17 @@
1# -*- coding: utf-8 -*-
2from mago.test_suite.gnome import GCalctoolTestSuite
3
4class GCalctoolCalculations(GCalctoolTestSuite):
5 def calculate(self, input, oracle, view='BASIC'):
6 if self.application.get_view() != view:
7 self.application.set_view(view)
8 self.application.push(input)
9 value = self.application.get_value()
10 if unicode(value) == unicode(oracle):
11 pass
12 else:
13 raise AssertionError, "Expected %s, calculator returned %s" % (oracle, value)
14
15if __name__ == "__main__":
16 gcalctool_calculations_test = GCalctoolCalculations()
17 gcalctool_calculations_test.run()
018
=== added file 'gcalctool/gcalctool_calculations.xml'
--- gcalctool/gcalctool_calculations.xml 1970-01-01 00:00:00 +0000
+++ gcalctool/gcalctool_calculations.xml 2009-09-03 12:20:23 +0000
@@ -0,0 +1,61 @@
1<?xml version="1.0"?>
2<suite name="gcalctool calculations">
3 <class>gcalctool_calculations.GCalctoolCalculations</class>
4 <description>
5 Tests that perform calculations and check the answer (cal-002)
6 </description>
7 <case name="1">
8 <method>calculate</method>
9 <description>3*4=12</description>
10 <args>
11 <input>3*4=</input>
12 <oracle>12</oracle>
13 <view>BASIC</view>
14 </args>
15 </case>
16 <case name="2">
17 <method>calculate</method>
18 <description>s9=3</description>
19 <args>
20 <input>Cs9=</input>
21 <oracle>3</oracle>
22 <view>ADVANCED</view>
23 </args>
24 </case>
25 <case name="3">
26 <method>calculate</method>
27 <description>1+1=2</description>
28 <args>
29 <input>1+1=</input>
30 <oracle>2</oracle>
31 <view>ADVANCED</view>
32 </args>
33 </case>
34 <case name="4">
35 <method>calculate</method>
36 <description>10-2=8</description>
37 <args>
38 <input>10-2=</input>
39 <oracle>8</oracle>
40 <view>PROGRAMMING</view>
41 </args>
42 </case>
43 <case name="5">
44 <method>calculate</method>
45 <description>14/2=7</description>
46 <args>
47 <input>14/2=</input>
48 <oracle>7</oracle>
49 <view>FINANCIAL</view>
50 </args>
51 </case>
52 <case name="6">
53 <method>calculate</method>
54 <description>5*6=30</description>
55 <args>
56 <input>5*6=</input>
57 <oracle>30</oracle>
58 <view>SCIENTIFIC</view>
59 </args>
60 </case>
61</suite>
062
=== added file 'gcalctool/gcalctool_views.py'
--- gcalctool/gcalctool_views.py 1970-01-01 00:00:00 +0000
+++ gcalctool/gcalctool_views.py 2009-09-19 03:28:17 +0000
@@ -0,0 +1,19 @@
1# -*- coding: utf-8 -*-
2from mago.test_suite.gnome import GCalctoolViewTestSuite
3
4class GCalctoolViews(GCalctoolViewTestSuite):
5 def changeViews(self, view, state, button):
6 value = self.application.get_value()
7 self.application.set_view(view)
8 if value != self.application.get_value():
9 raise AssertionError, "Displayed value changed upon changing views"
10 if state == "showing":
11 if self.application.showing(button) == False:
12 raise AssertionError, "Expected button is not showing"
13 elif state == "hidden":
14 if self.application.showing(button) == True:
15 raise AssertionError, "Button is not hidden as expected"
16
17if __name__ == "__main__":
18 gcalctool_views_test = GCalctoolViews()
19 gcalctool_views_test.run()
020
=== added file 'gcalctool/gcalctool_views.xml'
--- gcalctool/gcalctool_views.xml 1970-01-01 00:00:00 +0000
+++ gcalctool/gcalctool_views.xml 2009-09-19 03:28:17 +0000
@@ -0,0 +1,57 @@
1<?xml version="1.0"?>
2<suite name="gcalctool views">
3 <class>gcalctool_views.GCalctoolViews</class>
4 <description>
5 Tests that iterate through each calculator view (cal-001)
6 </description>
7 <case name="Advanced">
8 <method>changeViews</method>
9 <description>Change to the 'advanced' view and verify the square button
10 is showing</description>
11 <args>
12 <view>ADVANCED</view>
13 <state>showing</state>
14 <button>Square</button>
15 </args>
16 </case>
17 <case name="Financial">
18 <method>changeViews</method>
19 <description>Change to the 'financial' view and verify the future value
20 button is showing</description>
21 <args>
22 <view>FINANCIAL</view>
23 <state>showing</state>
24 <button>Future value</button>
25 </args>
26 </case>
27 <case name="Scientific">
28 <method>changeViews</method>
29 <description>Change to the 'scientific' view and verify the ln button
30 is showing</description>
31 <args>
32 <view>SCIENTIFIC</view>
33 <state>showing</state>
34 <button>ln</button>
35 </args>
36 </case>
37 <case name="Programming">
38 <method>changeViews</method>
39 <description>Change to the 'programming' view and verify the 1's button
40 is showing</description>
41 <args>
42 <view>PROGRAMMING</view>
43 <state>showing</state>
44 <button>1's</button>
45 </args>
46 </case>
47 <case name="Basic">
48 <method>changeViews</method>
49 <description>Change to the 'basic' view and verify the reciprocal button
50 is hidden</description>
51 <args>
52 <view>BASIC</view>
53 <state>hidden</state>
54 <button>Reciprocal</button>
55 </args>
56 </case>
57</suite>
058
=== modified file 'mago/application/gnome.py'
--- mago/application/gnome.py 2009-09-02 19:35:05 +0000
+++ mago/application/gnome.py 2009-09-11 04:58:37 +0000
@@ -6,6 +6,194 @@
6import ooldtp6import ooldtp
7import ldtp7import ldtp
8from .main import Application8from .main import Application
9from ..gconfwrapper import GConf
10import time
11
12class Calculator(Application):
13 """
14 The Calculator class contains methods for exercising the gcalctool application
15 """
16 LAUNCHER = "gcalctool"
17 WINDOW = "frmCalculator"
18 WINDOW_ADVANCED = "frmCalculator-Advanced"
19 WINDOW_FINANCIAL = "frmCalculator-Financial"
20 WINDOW_SCIENTIFIC = "frmCalculator-Scientific"
21 WINDOW_PROGRAMMING = "frmCalculator-Programming"
22 MNU_BASIC = "mnuBasic"
23 MNU_ADVANCED = "mnuAdvanced"
24 MNU_FINANCIAL = "mnuFinancial"
25 MNU_SCIENTIFIC = "mnuScientific"
26 MNU_PROGRAMMING = "mnuProgramming"
27 VIEWS = {"BASIC" : {"WINDOW" : WINDOW,
28 "MENU" : MNU_BASIC},
29 "ADVANCED" : {"WINDOW" : WINDOW_ADVANCED,
30 "MENU" : MNU_ADVANCED},
31 "FINANCIAL" : {"WINDOW" : WINDOW_FINANCIAL,
32 "MENU" : MNU_FINANCIAL},
33 "SCIENTIFIC" : {"WINDOW" : WINDOW_SCIENTIFIC,
34 "MENU" : MNU_SCIENTIFIC},
35 "PROGRAMMING" : {"WINDOW" : WINDOW_PROGRAMMING,
36 "MENU" : MNU_PROGRAMMING}}
37 BUTTONS = {"0" : "Numeric 0",
38 "1" : "Numeric 1",
39 "2" : "Numeric 2",
40 "3" : "Numeric 3",
41 "4" : "Numeric 4",
42 "5" : "Numeric 5",
43 "6" : "Numeric 6",
44 "7" : "Numeric 7",
45 "8" : "Numeric 8",
46 "9" : "Numeric 9",
47 "=" : "Calculate result",
48 "+" : "Add",
49 "-" : "Subtract",
50 "*" : "Multiply",
51 "/" : "Divide",
52 "c" : "Clear entry",
53 "C" : "Clear",
54 "." : "Numeric point",
55 "@" : "Square",
56 "s" : "Square root"}
57 EDITBAR_ROLE = "edit bar"
58 EDITBAR_INDEX = 0
59 SLEEP_DELAY = 2
60 GCONF_MODE_KEY = "/apps/gcalctool/mode"
61 GCONF_MODE_VAL = "BASIC"
62
63 def __init__(self):
64 Application.__init__(self)
65
66 def open(self):
67 """
68 Opens the application
69 """
70 try:
71 GConf.set_item(self.GCONF_MODE_KEY, self.GCONF_MODE_VAL)
72 except GConf.GConfError:
73 raise ldtp.LdtpExecutionError, "Could not set default view in gconf"
74 Application.open(self)
75
76 def showing(self, button):
77 """
78 Test whether the specified button is showing
79
80 @param button: Specify the button to test
81 @type button: string
82 @return: Value indicating whether the button is showing in the view
83 @rtype: boolean
84
85 >>> c = Calculator()
86 >>> c.open() # Calculator opens in BASIC view
87 >>> c.showing("Reciprocal")
88 False
89 >>> c.set_view("ADVANCED")
90 >>> c.showing("Reciprocal")
91 True
92 """
93 calculator = ooldtp.context(self.name)
94 try:
95 children = calculator.getchild(button,'push button')
96 for child in children:
97 childName=child.getName()
98 if calculator.hasstate(childName, ldtp.state.SHOWING):
99 return True
100 except ldtp.LdtpExecutionError:
101 raise ldtp.LdtpExecutionError, "Error locating button %s" % button
102 return False
103
104 def push(self, buttons):
105 """
106 Push the specified buttons in the calculator window.
107
108 >>> c = Calculator()
109 >>> c.open()
110 >>> c.push('2+2=')
111
112 @param buttons: Specify the buttons to push.
113 @type buttons: string
114 """
115 calculator = ooldtp.context(self.name)
116 for button in buttons:
117 try:
118 # The calculator has some buttons with the same names that are
119 # hidden depending on the view.
120 children = calculator.getchild(self.BUTTONS[button],'push button')
121 for child in children:
122 childName=child.getName()
123 if calculator.hasstate(childName, ldtp.state.SHOWING):
124 calculator.click(childName)
125 break
126 else:
127 raise LookupError, "Could not find button %s in current view" % button
128 except ldtp.LdtpExecutionError:
129 raise ldtp.LdtpExecutionError, "Error clicking button %s" % button
130
131 def get_view(self):
132 """
133 Get the current view of the calculator.
134
135 >>> c = Calculator()
136 >>> c.open()
137 >>> c.get_view()
138 'BASIC'
139
140 @return: The current view: BASIC, ADVANCED, FINANCIAL, SCIENTIFIC,
141 or PROGRAMMING
142 @rtype: string
143 """
144 windowname = self.name
145 for view in self.VIEWS:
146 if self.VIEWS[view]['WINDOW'] == windowname:
147 return view
148 raise LookupError, "Could not identify the current calculator view"
149
150 def set_view(self, new_view):
151 """
152 Change to the specified view in the calculator
153
154 >>> c = Calculator()
155 >>> c.open()
156 >>> c.set_view('ADVANCED')
157
158 @param new_view: Specify the new view. Valid values are:
159 BASIC, ADVANCED, FINANCIAL, SCIENTIFIC, PROGRAMMING
160 @type new_view: string
161 """
162 new_window_name = self.VIEWS[new_view]["WINDOW"]
163 new_view_menu_name = self.VIEWS[new_view]["MENU"]
164 calculator = ooldtp.context(self.name)
165 try:
166 mnu_new_view = calculator.getchild(new_view_menu_name)
167 except ldtp.LdtpExecutionError:
168 raise ldtp.LdtpExecutionError, "The menu item for the requested view was not found."
169
170 try:
171 mnu_new_view.selectmenuitem()
172 except ldtp.LdtpExecutionError:
173 raise ldtp.LdtpExecutionError, "There was a problem changing views."
174 self.set_name(new_window_name)
175 time.sleep(self.SLEEP_DELAY) # need to give mago some time to catch up to calc ui
176
177 def get_value(self):
178 """
179 Read the value from the calculator screen
180
181 >>> c = Calculator()
182 >>> c.open()
183 >>> c.push('2+2=')
184 >>> c.get_value()
185 u'4'
186
187 @return: The contents of the calculator's screen
188 @rtype: string
189 """
190 calculator = ooldtp.context(self.name)
191 try:
192 editBar = calculator.getchild('txtResultRegion') # txtResultRegion
193 value = editBar.gettextvalue()
194 except ldtp.LdtpExecutionError:
195 raise ldtp.LdtpExecutionError, "There was a problem reading the value."
196 return value
9197
10class GnomeScreenshot(Application):198class GnomeScreenshot(Application):
11 """199 """
@@ -252,7 +440,6 @@
252 except ldtp.LdtpExecutionError:440 except ldtp.LdtpExecutionError:
253 raise ldtp.LdtpExecutionError, "Window " + self.SAVE_FILE_WINDOW + " did not go away"441 raise ldtp.LdtpExecutionError, "Window " + self.SAVE_FILE_WINDOW + " did not go away"
254442
255
256class Seahorse(Application):443class Seahorse(Application):
257 """444 """
258 Seahorse manages the Seahorse application.445 Seahorse manages the Seahorse application.
259446
=== modified file 'mago/test_suite/gnome.py'
--- mago/test_suite/gnome.py 2009-08-25 18:33:48 +0000
+++ mago/test_suite/gnome.py 2009-09-09 19:03:31 +0000
@@ -4,7 +4,30 @@
4"""4"""
5import ldtp, ooldtp5import ldtp, ooldtp
6from .main import SingleApplicationTestSuite6from .main import SingleApplicationTestSuite
7from ..application.gnome import Application, GnomeScreenshot, Seahorse, GEdit7from ..application.gnome import Application, Seahorse, GEdit, GnomeScreenshot, Calculator
8
9class GCalctoolTestSuite(SingleApplicationTestSuite):
10 """
11 Default test suite for Calculator
12 """
13 APPLICATION_FACTORY = Calculator
14 def setup(self):
15 self.application.open()
16 self.application.push("C")
17
18 def teardown(self):
19 self.application.close()
20
21 def cleanup(self):
22 pass
23
24class GCalctoolViewTestSuite(GCalctoolTestSuite):
25 """
26 Test suite for views populates the screen with some data in setup
27 """
28 def setup(self):
29 GCalctoolTestSuite.setup(self)
30 self.application.push("13.37")
831
9class GnomeScreenshotTestSuite(SingleApplicationTestSuite):32class GnomeScreenshotTestSuite(SingleApplicationTestSuite):
10 APPLICATION_FACTORY = GnomeScreenshot 33 APPLICATION_FACTORY = GnomeScreenshot

Subscribers

People subscribed via source and target branches

to status/vote changes: