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

Proposed by James Tatum
Status: Superseded
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
Javier Collado (community) Needs Information
Ara Pulido Approve
Review via email: mp+11573@code.launchpad.net

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

This proposal has been superseded by a proposal from 2009-09-22.

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 :

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.

lp:~jtatum/mago/gcalctool updated
120. By James Tatum

Removing remap per Nagappan's suggestion

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

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 :

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 :

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
lp:~jtatum/mago/gcalctool updated
121. By James Tatum

Integrating the button test with the view change per JCollado's suggestion

122. By James Tatum

Merging from trunk

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'gcalctool'
2=== added file 'gcalctool/README'
3--- gcalctool/README 1970-01-01 00:00:00 +0000
4+++ gcalctool/README 2009-09-11 02:51:23 +0000
5@@ -0,0 +1,46 @@
6+GCALCTOOL TESTS
7+-----------
8+Tests that verify calculator functionality.
9+
10+Safety
11+------
12+These tests will change the calculator's view, which is loaded at startup.
13+Otherwise, they are safe to run.
14+
15+Configuration
16+-------------
17+No configuration is needed
18+
19+Version
20+-------
21+Tests were updated for Ubuntu Karmic
22+
23+Available Testsuites
24+--------------------
25+
26+* gcalctool views (testcases wiki: cal-001)
27+ Tools that exercise the views in gcalctool
28+ These tests will also fail if the title bar text is incorrect
29+ - Advanced
30+ - Advanced button
31+ Verify that the Square button exists in the current view
32+ - Financial
33+ - Financial button
34+ Verify that the Future value button exists in the current view
35+ - Scientific
36+ - Scientific button
37+ Verify that the ln button exists in the current view
38+ - Programming
39+ - Programming button
40+ Verify that the 1's button exists in the current view
41+ - Basic
42+ - Basic button
43+ Verify that the Reciprocal button is hidden in the current view
44+* gcalctool calculations (testcases wiki: cal-002)
45+ Tools that perform calculations in gcalctool and verify the results
46+ - 3*4=12
47+ - Square root 9=3
48+ - 1+1=2
49+ - 10-2=8
50+ - 14/2=7
51+ - 5*6=30
52
53=== added file 'gcalctool/gcalctool_calculations.py'
54--- gcalctool/gcalctool_calculations.py 1970-01-01 00:00:00 +0000
55+++ gcalctool/gcalctool_calculations.py 2009-09-10 14:53:24 +0000
56@@ -0,0 +1,17 @@
57+# -*- coding: utf-8 -*-
58+from mago.test_suite.gnome import GCalctoolTestSuite
59+
60+class GCalctoolCalculations(GCalctoolTestSuite):
61+ def calculate(self, input, oracle, view='BASIC'):
62+ if self.application.get_view() != view:
63+ self.application.set_view(view)
64+ self.application.push(input)
65+ value = self.application.get_value()
66+ if unicode(value) == unicode(oracle):
67+ pass
68+ else:
69+ raise AssertionError, "Expected %s, calculator returned %s" % (oracle, value)
70+
71+if __name__ == "__main__":
72+ gcalctool_calculations_test = GCalctoolCalculations()
73+ gcalctool_calculations_test.run()
74
75=== added file 'gcalctool/gcalctool_calculations.xml'
76--- gcalctool/gcalctool_calculations.xml 1970-01-01 00:00:00 +0000
77+++ gcalctool/gcalctool_calculations.xml 2009-09-03 12:20:23 +0000
78@@ -0,0 +1,61 @@
79+<?xml version="1.0"?>
80+<suite name="gcalctool calculations">
81+ <class>gcalctool_calculations.GCalctoolCalculations</class>
82+ <description>
83+ Tests that perform calculations and check the answer (cal-002)
84+ </description>
85+ <case name="1">
86+ <method>calculate</method>
87+ <description>3*4=12</description>
88+ <args>
89+ <input>3*4=</input>
90+ <oracle>12</oracle>
91+ <view>BASIC</view>
92+ </args>
93+ </case>
94+ <case name="2">
95+ <method>calculate</method>
96+ <description>s9=3</description>
97+ <args>
98+ <input>Cs9=</input>
99+ <oracle>3</oracle>
100+ <view>ADVANCED</view>
101+ </args>
102+ </case>
103+ <case name="3">
104+ <method>calculate</method>
105+ <description>1+1=2</description>
106+ <args>
107+ <input>1+1=</input>
108+ <oracle>2</oracle>
109+ <view>ADVANCED</view>
110+ </args>
111+ </case>
112+ <case name="4">
113+ <method>calculate</method>
114+ <description>10-2=8</description>
115+ <args>
116+ <input>10-2=</input>
117+ <oracle>8</oracle>
118+ <view>PROGRAMMING</view>
119+ </args>
120+ </case>
121+ <case name="5">
122+ <method>calculate</method>
123+ <description>14/2=7</description>
124+ <args>
125+ <input>14/2=</input>
126+ <oracle>7</oracle>
127+ <view>FINANCIAL</view>
128+ </args>
129+ </case>
130+ <case name="6">
131+ <method>calculate</method>
132+ <description>5*6=30</description>
133+ <args>
134+ <input>5*6=</input>
135+ <oracle>30</oracle>
136+ <view>SCIENTIFIC</view>
137+ </args>
138+ </case>
139+</suite>
140
141=== added file 'gcalctool/gcalctool_views.py'
142--- gcalctool/gcalctool_views.py 1970-01-01 00:00:00 +0000
143+++ gcalctool/gcalctool_views.py 2009-09-11 02:53:10 +0000
144@@ -0,0 +1,21 @@
145+# -*- coding: utf-8 -*-
146+from mago.test_suite.gnome import GCalctoolViewTestSuite
147+
148+class GCalctoolViews(GCalctoolViewTestSuite):
149+ def changeViews(self, view):
150+ value = self.application.get_value()
151+ self.application.set_view(view)
152+ if value != self.application.get_value():
153+ raise AssertionError, "Displayed value changed upon changing views"
154+
155+ def showing(self, button):
156+ if self.application.showing(button) == False:
157+ raise AssertionError, "Button is not showing"
158+
159+ def hidden(self, button):
160+ if self.application.showing(button) == True:
161+ raise AssertionError, "Button is not hidden"
162+
163+if __name__ == "__main__":
164+ gcalctool_views_test = GCalctoolViews()
165+ gcalctool_views_test.run()
166
167=== added file 'gcalctool/gcalctool_views.xml'
168--- gcalctool/gcalctool_views.xml 1970-01-01 00:00:00 +0000
169+++ gcalctool/gcalctool_views.xml 2009-09-11 02:51:23 +0000
170@@ -0,0 +1,77 @@
171+<?xml version="1.0"?>
172+<suite name="gcalctool views">
173+ <class>gcalctool_views.GCalctoolViews</class>
174+ <description>
175+ Tests that iterate through each calculator view (cal-001)
176+ </description>
177+ <case name="Advanced">
178+ <method>changeViews</method>
179+ <description>Change to the 'advanced' view</description>
180+ <args>
181+ <view>ADVANCED</view>
182+ </args>
183+ </case>
184+ <case name="Advanced button">
185+ <method>showing</method>
186+ <description>Verify the square button is showing</description>
187+ <args>
188+ <button>Square</button>
189+ </args>
190+ </case>
191+ <case name="Financial">
192+ <method>changeViews</method>
193+ <description>Change to the 'financial' view</description>
194+ <args>
195+ <view>FINANCIAL</view>
196+ </args>
197+ </case>
198+ <case name="Financial button">
199+ <method>showing</method>
200+ <description>Verify the future value button is showing</description>
201+ <args>
202+ <button>Future value</button>
203+ </args>
204+ </case>
205+ <case name="Scientific">
206+ <method>changeViews</method>
207+ <description>Change to the 'scientific' view</description>
208+ <args>
209+ <view>SCIENTIFIC</view>
210+ </args>
211+ </case>
212+ <case name="Scientific button">
213+ <method>showing</method>
214+ <description>Verify the ln button is showing</description>
215+ <args>
216+ <button>ln</button>
217+ </args>
218+ </case>
219+ <case name="Programming">
220+ <method>changeViews</method>
221+ <description>Change to the 'programming' view</description>
222+ <args>
223+ <view>PROGRAMMING</view>
224+ </args>
225+ </case>
226+ <case name="Programming button">
227+ <method>showing</method>
228+ <description>Verify the 1's button is showing</description>
229+ <args>
230+ <button>1's</button>
231+ </args>
232+ </case>
233+ <case name="Basic">
234+ <method>changeViews</method>
235+ <description>Change to the 'basic' view</description>
236+ <args>
237+ <view>BASIC</view>
238+ </args>
239+ </case>
240+ <case name="Basic button">
241+ <method>hidden</method>
242+ <description>Verify the reciprocal button is hidden</description>
243+ <args>
244+ <button>Reciprocal</button>
245+ </args>
246+ </case>
247+</suite>
248
249=== modified file 'mago/application/gnome.py'
250--- mago/application/gnome.py 2009-09-02 19:35:05 +0000
251+++ mago/application/gnome.py 2009-09-11 02:51:23 +0000
252@@ -6,6 +6,195 @@
253 import ooldtp
254 import ldtp
255 from .main import Application
256+from ..gconfwrapper import GConf
257+import time
258+
259+class Calculator(Application):
260+ """
261+ The Calculator class contains methods for exercising the gcalctool application
262+ """
263+ LAUNCHER = "gcalctool"
264+ WINDOW = "frmCalculator"
265+ WINDOW_ADVANCED = "frmCalculator-Advanced"
266+ WINDOW_FINANCIAL = "frmCalculator-Financial"
267+ WINDOW_SCIENTIFIC = "frmCalculator-Scientific"
268+ WINDOW_PROGRAMMING = "frmCalculator-Programming"
269+ MNU_BASIC = "mnuBasic"
270+ MNU_ADVANCED = "mnuAdvanced"
271+ MNU_FINANCIAL = "mnuFinancial"
272+ MNU_SCIENTIFIC = "mnuScientific"
273+ MNU_PROGRAMMING = "mnuProgramming"
274+ VIEWS = {"BASIC" : {"WINDOW" : WINDOW,
275+ "MENU" : MNU_BASIC},
276+ "ADVANCED" : {"WINDOW" : WINDOW_ADVANCED,
277+ "MENU" : MNU_ADVANCED},
278+ "FINANCIAL" : {"WINDOW" : WINDOW_FINANCIAL,
279+ "MENU" : MNU_FINANCIAL},
280+ "SCIENTIFIC" : {"WINDOW" : WINDOW_SCIENTIFIC,
281+ "MENU" : MNU_SCIENTIFIC},
282+ "PROGRAMMING" : {"WINDOW" : WINDOW_PROGRAMMING,
283+ "MENU" : MNU_PROGRAMMING}}
284+ BUTTONS = {"0" : "Numeric 0",
285+ "1" : "Numeric 1",
286+ "2" : "Numeric 2",
287+ "3" : "Numeric 3",
288+ "4" : "Numeric 4",
289+ "5" : "Numeric 5",
290+ "6" : "Numeric 6",
291+ "7" : "Numeric 7",
292+ "8" : "Numeric 8",
293+ "9" : "Numeric 9",
294+ "=" : "Calculate result",
295+ "+" : "Add",
296+ "-" : "Subtract",
297+ "*" : "Multiply",
298+ "/" : "Divide",
299+ "c" : "Clear entry",
300+ "C" : "Clear",
301+ "." : "Numeric point",
302+ "@" : "Square",
303+ "s" : "Square root"}
304+ EDITBAR_ROLE = "edit bar"
305+ EDITBAR_INDEX = 0
306+ SLEEP_DELAY = 2
307+ GCONF_MODE_KEY = "/apps/gcalctool/mode"
308+ GCONF_MODE_VAL = "BASIC"
309+
310+ def __init__(self):
311+ Application.__init__(self)
312+
313+ def open(self):
314+ """
315+ Opens the application
316+ """
317+ try:
318+ GConf.set_item(self.GCONF_MODE_KEY, self.GCONF_MODE_VAL)
319+ except GConf.GConfError:
320+ raise ldtp.LdtpExecutionError, "Could not set default view in gconf"
321+ Application.open(self)
322+
323+ def showing(self, button):
324+ """
325+ Test whether the specified button is showing
326+
327+ @param button: Specify the button to test
328+ @type button: string
329+ @return: Value indicating whether the button is showing in the view
330+ @rtype: boolean
331+
332+ >>> c = Calculator()
333+ >>> c.open() # Calculator opens in BASIC view
334+ >>> c.showing("Reciprocal")
335+ False
336+ >>> c.set_view("ADVANCED")
337+ >>> c.showing("Reciprocal")
338+ True
339+ """
340+ calculator = ooldtp.context(self.name)
341+ try:
342+ children = calculator.getchild(button,'push button')
343+ for child in children:
344+ childName=child.getName()
345+ if calculator.hasstate(childName, ldtp.state.SHOWING):
346+ return True
347+ except ldtp.LdtpExecutionError:
348+ raise ldtp.LdtpExecutionError, "Error locating button %s" % button
349+ return False
350+
351+ def push(self, buttons):
352+ """
353+ Push the specified buttons in the calculator window.
354+
355+ >>> c = Calculator()
356+ >>> c.open()
357+ >>> c.push('2+2=')
358+
359+ @param buttons: Specify the buttons to push.
360+ @type buttons: string
361+ """
362+ calculator = ooldtp.context(self.name)
363+ for button in buttons:
364+ try:
365+ # The calculator has some buttons with the same names that are
366+ # hidden depending on the view.
367+ children = calculator.getchild(self.BUTTONS[button],'push button')
368+ for child in children:
369+ childName=child.getName()
370+ if calculator.hasstate(childName, ldtp.state.SHOWING):
371+ calculator.click(childName)
372+ break
373+ else:
374+ raise LookupError, "Could not find button %s in current view" % button
375+ except ldtp.LdtpExecutionError:
376+ raise ldtp.LdtpExecutionError, "Error clicking button %s" % button
377+
378+ def get_view(self):
379+ """
380+ Get the current view of the calculator.
381+
382+ >>> c = Calculator()
383+ >>> c.open()
384+ >>> c.get_view()
385+ 'BASIC'
386+
387+ @return: The current view: BASIC, ADVANCED, FINANCIAL, SCIENTIFIC,
388+ or PROGRAMMING
389+ @rtype: string
390+ """
391+ windowname = self.name
392+ for view in self.VIEWS:
393+ if self.VIEWS[view]['WINDOW'] == windowname:
394+ return view
395+ raise LookupError, "Could not identify the current calculator view"
396+
397+ def set_view(self, new_view):
398+ """
399+ Change to the specified view in the calculator
400+
401+ >>> c = Calculator()
402+ >>> c.open()
403+ >>> c.set_view('ADVANCED')
404+
405+ @param new_view: Specify the new view. Valid values are:
406+ BASIC, ADVANCED, FINANCIAL, SCIENTIFIC, PROGRAMMING
407+ @type new_view: string
408+ """
409+ new_window_name = self.VIEWS[new_view]["WINDOW"]
410+ new_view_menu_name = self.VIEWS[new_view]["MENU"]
411+ calculator = ooldtp.context(self.name)
412+ try:
413+ mnu_new_view = calculator.getchild(new_view_menu_name)
414+ except ldtp.LdtpExecutionError:
415+ raise ldtp.LdtpExecutionError, "The menu item for the requested view was not found."
416+
417+ try:
418+ mnu_new_view.selectmenuitem()
419+ except ldtp.LdtpExecutionError:
420+ raise ldtp.LdtpExecutionError, "There was a problem changing views."
421+ self.set_name(new_window_name)
422+ time.sleep(self.SLEEP_DELAY) # need to give mago some time to catch up to calc ui
423+ self.remap() # tell mago about the new frm name and remap everything
424+
425+ def get_value(self):
426+ """
427+ Read the value from the calculator screen
428+
429+ >>> c = Calculator()
430+ >>> c.open()
431+ >>> c.push('2+2=')
432+ >>> c.get_value()
433+ u'4'
434+
435+ @return: The contents of the calculator's screen
436+ @rtype: string
437+ """
438+ calculator = ooldtp.context(self.name)
439+ try:
440+ editBar = calculator.getchild('txtResultRegion') # txtResultRegion
441+ value = editBar.gettextvalue()
442+ except ldtp.LdtpExecutionError:
443+ raise ldtp.LdtpExecutionError, "There was a problem reading the value."
444+ return value
445
446 class GnomeScreenshot(Application):
447 """
448@@ -252,7 +441,6 @@
449 except ldtp.LdtpExecutionError:
450 raise ldtp.LdtpExecutionError, "Window " + self.SAVE_FILE_WINDOW + " did not go away"
451
452-
453 class Seahorse(Application):
454 """
455 Seahorse manages the Seahorse application.
456
457=== modified file 'mago/test_suite/gnome.py'
458--- mago/test_suite/gnome.py 2009-08-25 18:33:48 +0000
459+++ mago/test_suite/gnome.py 2009-09-09 19:03:31 +0000
460@@ -4,7 +4,30 @@
461 """
462 import ldtp, ooldtp
463 from .main import SingleApplicationTestSuite
464-from ..application.gnome import Application, GnomeScreenshot, Seahorse, GEdit
465+from ..application.gnome import Application, Seahorse, GEdit, GnomeScreenshot, Calculator
466+
467+class GCalctoolTestSuite(SingleApplicationTestSuite):
468+ """
469+ Default test suite for Calculator
470+ """
471+ APPLICATION_FACTORY = Calculator
472+ def setup(self):
473+ self.application.open()
474+ self.application.push("C")
475+
476+ def teardown(self):
477+ self.application.close()
478+
479+ def cleanup(self):
480+ pass
481+
482+class GCalctoolViewTestSuite(GCalctoolTestSuite):
483+ """
484+ Test suite for views populates the screen with some data in setup
485+ """
486+ def setup(self):
487+ GCalctoolTestSuite.setup(self)
488+ self.application.push("13.37")
489
490 class GnomeScreenshotTestSuite(SingleApplicationTestSuite):
491 APPLICATION_FACTORY = GnomeScreenshot

Subscribers

People subscribed via source and target branches

to status/vote changes: