A4

Merge lp:~andrea.corbellini/a4/test-suite into lp:a4

Proposed by Andrea Corbellini
Status: Merged
Approved by: Andrea Corbellini
Approved revision: 32
Merged at revision: 52
Proposed branch: lp:~andrea.corbellini/a4/test-suite
Merge into: lp:a4
Diff against target: 777 lines (+443/-288)
8 files modified
Makefile (+4/-0)
test.py (+45/-0)
test_images/drawing.svg (+0/-118)
test_images/roi.svg (+0/-170)
tests/images/drawing.svg (+118/-0)
tests/images/roi.svg (+170/-0)
tests/opening_files.py (+39/-0)
tests/testhelpers.py (+67/-0)
To merge this branch: bzr merge lp:~andrea.corbellini/a4/test-suite
Reviewer Review Type Date Requested Status
Andrea Gualano Approve
Andrea Colangelo Needs Fixing
Review via email: mp+27716@code.launchpad.net

Description of the change

This branch adds the code for a test suite. I've used LDTP as testing framework. It allows us to start and handle windows in a simple manner (however, when a test fails it behaves badly).

To post a comment you must log in.
Revision history for this message
Andrea Gualano (andrea-gualano) wrote :

I couldn't make the tests work:

$ bzr branch lp:~andrea.corbellini/a4/test-suite
Branched 25 revision(s).
$ cd test-suite/
$ make check
python test.py

** (-c:2332): WARNING **: Trying to register gtype 'WnckWindowState' as enum when in fact it is of type 'GFlags'

** (-c:2332): WARNING **: Trying to register gtype 'WnckWindowActions' as enum when in fact it is of type 'GFlags'

** (-c:2332): WARNING **: Trying to register gtype 'WnckWindowMoveResizeMask' as enum when in fact it is of type 'GFlags'
GTK Accessibility Module initialized
GTK Accessibility Module initialized
GTK Accessibility Module initialized
Failed test case: opening_files.TestOpeningFiles.test_open_existent_file
  Traceback (most recent call last):
    File "tests/opening_files.py", line 20, in test_open_existent_file
      dialog.settextvalue('txtLocation', TEST_IMAGE_FILE)
    File "tests/testhelpers.py", line 32, in wrapper
      retval = ldtp_method(self.window_id, *args, **kwargs)
    File "/usr/lib/pymodules/python2.6/ldtp/client.py", line 50, in __call__
      return self.__send(self.__name, args)
    File "/usr/lib/python2.6/xmlrpclib.py", line 1489, in __request
      verbose=self.__verbose
    File "/usr/lib/pymodules/python2.6/ldtp/client.py", line 99, in request
      raise LdtpExecutionError(e.faultString)
  LdtpExecutionError: Unable to find object name "txtLocation" in application map
Failed test case: opening_files.TestOpeningFiles.test_open_incorrect_file
  Traceback (most recent call last):
    File "tests/opening_files.py", line 57, in test_open_incorrect_file
      dialog.settextvalue('txtLocation', os.path.abspath(__file__))
    File "tests/testhelpers.py", line 32, in wrapper
      retval = ldtp_method(self.window_id, *args, **kwargs)
    File "/usr/lib/pymodules/python2.6/ldtp/client.py", line 50, in __call__
      return self.__send(self.__name, args)
    File "/usr/lib/python2.6/xmlrpclib.py", line 1489, in __request
      verbose=self.__verbose
    File "/usr/lib/pymodules/python2.6/ldtp/client.py", line 99, in request
      raise LdtpExecutionError(e.faultString)
  LdtpExecutionError: Unable to find object name "txtLocation" in application map
Failed test case: opening_files.TestOpeningFiles.test_open_inexistent_file
  Traceback (most recent call last):
    File "tests/opening_files.py", line 38, in test_open_inexistent_file
      dialog.settextvalue('txtLocation', 'this-file-does-not-exist')
    File "tests/testhelpers.py", line 32, in wrapper
      retval = ldtp_method(self.window_id, *args, **kwargs)
    File "/usr/lib/pymodules/python2.6/ldtp/client.py", line 50, in __call__
      return self.__send(self.__name, args)
    File "/usr/lib/python2.6/xmlrpclib.py", line 1489, in __request
      verbose=self.__verbose
    File "/usr/lib/pymodules/python2.6/ldtp/client.py", line 99, in request
      raise LdtpExecutionError(e.faultString)
  LdtpExecutionError: Unable to find object name "txtLocation" in application map
Ran 3 tests (3 failed)

review: Needs Fixing
Revision history for this message
Andrea Gualano (andrea-gualano) wrote :

Hi,
the roi.svg test image is something I use to develop A4; all the objects are positioned to allow me to see the trajectories during transitions and so on. Probably it's only useful to me, but I'd prefer to have it in the mainline repository so that I can open it any time I run a test version.

Also, you made several changes to the properties of the objects in A4_nested_transforms.svg; maybe they were useful that way (or maybe not, we should ask Gaspa).

Anyway, the handling of test files is a complex matter, I would split the deletion of test_images/ into a separate branch so that we can finalize this one before taking a definitive position on the test images directory.

Revision history for this message
Andrea Gualano (andrea-gualano) wrote :

One more (possibly unrelated) thing: LDTP is a GUI automation framework, which is cool for testing that the GUI remains functional.
I think we should also have traditional unit tests for things like SVG parsing, maths, rendering.
Perhaps we should make separate make targets for unit and GUI tests.

Revision history for this message
Andrea Corbellini (andrea.corbellini) wrote :

> I couldn't make the tests work...
I suppose that's because you have set Italian as your language. Using English should work, could you confirm, please?

> the roi.svg test image is something I use to develop A4...
Then I will re-add it to the branch. I deleted it because I found it very similar to the other image, sorry.

> Also, you made several changes to the properties of the objects in A4_nested_transforms.svg...
I've just run the 'Delete unused defs' function of Inkscape, so it should be fine.

> Anyway, the handling of test files is a complex matter...
I will put them in tests/images. However I would like to give them more descriptive names, but this can be done in the future.

> One more (possibly unrelated) thing: LDTP is a GUI automation framework...
I generally prefer to write short merge proposals focused on a single feature to make them easier to review. That's why you see just the behaviour-driven tests, but writing tests for the code itself is on my roadmap too (in fact, many things are difficult to test with LDTP).

Revision history for this message
Andrea Gualano (andrea-gualano) wrote :

> I suppose that's because you have set Italian as your language. Using English
> should work, could you confirm, please?

No, my system is set up in English.
I am using Lucid on amd64.

Also, if I have other applications open when I run the tests, they will be closed as if I had clicked on the X button. Don't know if this is useful.

> A4_nested_transforms.svg...
> I've just run the 'Delete unused defs' function of Inkscape, so it should be
> fine.

Yes. After a closer look, I see that the only properties that have changed are in the inkscape namespace, so I don't think we are using them.

> > Anyway, the handling of test files is a complex matter...
> I will put them in tests/images. However I would like to give them more
> descriptive names, but this can be done in the future.

This is okay for now.
In the future we may have to handle three different kinds of test presentations:
- images that will actually be installed on the user's system (in /usr/share/a4/...); ideally these should be beautiful presentations about A4's amazing features, but for now we will have to use the images we have; these are also useful for samples and documentations, see here for example: http://wiki.ubuntu-it.org/GruppoTest/Casi/A4
- images used for development, with a special selection of items, transformations and so on;
- images used by the automated tests.

Revision history for this message
Andrea Gualano (andrea-gualano) wrote :

Same failure on a different machine: Lucid x86, English :-(

Revision history for this message
Andrea Corbellini (andrea.corbellini) wrote :

I've fixed the test. The problem was that by default the 'Location' textbox of the 'Open file' dialog is hidden on GNOME.

Revision history for this message
Andrea Gualano (andrea-gualano) wrote :

GREAT!
I'm going to to test it ASAP.

Revision history for this message
Andrea Colangelo (warp10) wrote :

Looks like we still need some work aroun it. I tried to run test.py and I got this:

andrea@starfleet:~/A4/a4$ python ./test.py

** (-c:18310): WARNING **: Trying to register gtype 'WnckWindowState' as enum when in fact it is of type 'GFlags'

** (-c:18310): WARNING **: Trying to register gtype 'WnckWindowActions' as enum when in fact it is of type 'GFlags'

** (-c:18310): WARNING **: Trying to register gtype 'WnckWindowMoveResizeMask' as enum when in fact it is of type 'GFlags'
GTK Accessibility Module initialized
GTK Accessibility Module initialized
Traceback (most recent call last):
  File "/home/andrea/A4/a4/a4lib/app.py", line 198, in on_drawing_area_expose
    self.player.render(context)
  File "/home/andrea/A4/a4/a4lib/player.py", line 139, in render
    if not self.presentation:
AttributeError: 'CairoPlayer' object has no attribute 'presentation'
Traceback (most recent call last):
  File "/home/andrea/A4/a4/a4lib/app.py", line 198, in on_drawing_area_expose
    self.player.render(context)
  File "/home/andrea/A4/a4/a4lib/player.py", line 139, in render
    if not self.presentation:
AttributeError: 'CairoPlayer' object has no attribute 'presentation'
GTK Accessibility Module initialized
Traceback (most recent call last):
  File "/home/andrea/A4/a4/a4lib/app.py", line 198, in on_drawing_area_expose
    self.player.render(context)
  File "/home/andrea/A4/a4/a4lib/player.py", line 139, in render
    if not self.presentation:
AttributeError: 'CairoPlayer' object has no attribute 'presentation'
Traceback (most recent call last):
  File "/home/andrea/A4/a4/a4lib/app.py", line 198, in on_drawing_area_expose
    self.player.render(context)
  File "/home/andrea/A4/a4/a4lib/player.py", line 139, in render
    if not self.presentation:
AttributeError: 'CairoPlayer' object has no attribute 'presentation'
Traceback (most recent call last):
  File "/home/andrea/A4/a4/a4lib/app.py", line 198, in on_drawing_area_expose
    self.player.render(context)
  File "/home/andrea/A4/a4/a4lib/player.py", line 139, in render
    if not self.presentation:
AttributeError: 'CairoPlayer' object has no attribute 'presentation'
Ran 3 tests without failures
andrea@starfleet:~/A4/a4$ Traceback (most recent call last):
  File "/home/andrea/A4/a4/a4lib/app.py", line 198, in on_drawing_area_expose
    self.player.render(context)
  File "/home/andrea/A4/a4/a4lib/player.py", line 139, in render
    if not self.presentation:
AttributeError: 'CairoPlayer' object has no attribute 'presentation'

Immediately before showing the Traceback, it tried to close the terminal (terminator prevented it).

review: Needs Fixing
Revision history for this message
Andrea Corbellini (andrea.corbellini) wrote :

The tracebacks you are seeing are bugs in the trunk branch (and that's why I like unit testing). The test suite should be fine.

Revision history for this message
Andrea Gualano (andrea-gualano) wrote :
Download full text (3.4 KiB)

Sadly, it's still not working. This time it can't find the control called "tbtnTypeafilename". Also, even in the previous version the Location text field was visible, so the problem seems to be that it can't find the controls by name.

This is what happens: an A4 main window opens, then an Open File dialog titled "a4" opens and gets focus, then nothing happens for a few seconds; then it happens again twice (a main window and a dialog for each test). None of these windows gets closed automatically.
It doesn't close random windows anymore.

Is there any way to see which window the "dialog" variable actually captures? or to get the names of the window controls?

Output:

$ make check
python test.py

** (-c:23319): WARNING **: Trying to register gtype 'WnckWindowState' as enum when in fact it is of type 'GFlags'

** (-c:23319): WARNING **: Trying to register gtype 'WnckWindowActions' as enum when in fact it is of type 'GFlags'

** (-c:23319): WARNING **: Trying to register gtype 'WnckWindowMoveResizeMask' as enum when in fact it is of type 'GFlags'
GTK Accessibility Module initialized
GTK Accessibility Module initialized
GTK Accessibility Module initialized
Failed test case: opening_files.TestOpeningFiles.test_open_existent_file
  Traceback (most recent call last):
    File "tests/opening_files.py", line 24, in test_open_existent_file
      dialog.click('tbtnTypeafilename')
    File "tests/testhelpers.py", line 32, in wrapper
      retval = ldtp_method(self.window_id, *args, **kwargs)
    File "/usr/lib/pymodules/python2.6/ldtp/client.py", line 50, in __call__
      return self.__send(self.__name, args)
    File "/usr/lib/python2.6/xmlrpclib.py", line 1489, in __request
      verbose=self.__verbose
    File "/usr/lib/pymodules/python2.6/ldtp/client.py", line 99, in request
      raise LdtpExecutionError(e.faultString)
  LdtpExecutionError: Unable to find object name "tbtnTypeafilename" in application map
Failed test case: opening_files.TestOpeningFiles.test_open_incorrect_file
  Traceback (most recent call last):
    File "tests/opening_files.py", line 69, in test_open_incorrect_file
      dialog.click('tbtnTypeafilename')
    File "tests/testhelpers.py", line 32, in wrapper
      retval = ldtp_method(self.window_id, *args, **kwargs)
    File "/usr/lib/pymodules/python2.6/ldtp/client.py", line 50, in __call__
      return self.__send(self.__name, args)
    File "/usr/lib/python2.6/xmlrpclib.py", line 1489, in __request
      verbose=self.__verbose
    File "/usr/lib/pymodules/python2.6/ldtp/client.py", line 99, in request
      raise LdtpExecutionError(e.faultString)
  LdtpExecutionError: Unable to find object name "tbtnTypeafilename" in application map
Failed test case: opening_files.TestOpeningFiles.test_open_inexistent_file
  Traceback (most recent call last):
    File "tests/opening_files.py", line 46, in test_open_inexistent_file
      dialog.click('tbtnTypeafilename')
    File "tests/testhelpers.py", line 32, in wrapper
      retval = ldtp_method(self.window_id, *args, **kwargs)
    File "/usr/lib/pymodules/python2.6/ldtp/client.py", line 50, in __call__
      return self.__send(self.__name, args)
    File "/usr/lib/python2.6/xmlrpclib.py"...

Read more...

review: Needs Fixing
Revision history for this message
Andrea Corbellini (andrea.corbellini) wrote :

With the latest revision (32) now everything should work. Instead of opening files using the dialog (that is the cause of the problems), I've given the file name as an argument to A4.

The only exceptions that you should see when running `make check` should be two `AttributeError`s, but these are bugs in the software (that I'd happy to fix with my next branch), not something in the test suite itself.

As usual, feel free to ask if you have questions, doubts or problems.

Revision history for this message
Andrea Gualano (andrea-gualano) wrote :

> Ran 3 tests without failures

It finally works for me too :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Makefile'
--- Makefile 2010-07-03 00:05:02 +0000
+++ Makefile 2010-07-14 09:01:45 +0000
@@ -7,5 +7,9 @@
7install: build7install: build
8 python setup.py install8 python setup.py install
99
10check:
11 python test.py
12
10clean:13clean:
14 rm -rf build
11 find . -name "*.pyc" -o -name "*.pyo" -o -name "*~" | xargs rm -f15 find . -name "*.pyc" -o -name "*.pyo" -o -name "*~" | xargs rm -f
1216
=== added file 'test.py'
--- test.py 1970-01-01 00:00:00 +0000
+++ test.py 2010-07-14 09:01:45 +0000
@@ -0,0 +1,45 @@
1# Copyright 2010 A4 Developers. This software is licensed under the
2# GNU General Public License version 3 (see the file COPYING).
3
4"""Test suite runner for A4."""
5
6import os
7import sys
8import unittest
9
10
11def main():
12 """Run the test suite."""
13 total_tests_run = 0
14 total_failures = 0
15 sys.path.insert(0, 'tests')
16 loader = unittest.TestLoader()
17
18 for file_name in os.listdir('tests'):
19 if not file_name.endswith('.py'):
20 continue
21
22 # Get all the test cases from the module.
23 module = __import__(file_name[:-3])
24 test = loader.loadTestsFromModule(module)
25 result = test.run(unittest.TestResult())
26
27 # Report the failures (if any).
28 failures = result.errors + result.failures
29 for parser, traceback in failures:
30 print 'Failed test case:', parser.id()
31 print '\n'.join(' ' + line for line in traceback.splitlines())
32
33 total_tests_run += result.testsRun
34 total_failures += len(failures)
35
36 # Give a summary of the tests run.
37 if total_failures:
38 print 'Ran {0} tests ({1} failed)'.format(
39 total_tests_run, total_failures)
40 else:
41 print 'Ran {0} tests without failures'.format(total_tests_run)
42
43
44if __name__ == '__main__':
45 main()
046
=== removed file 'test_images/drawing.svg'
--- test_images/drawing.svg 2010-07-03 00:05:02 +0000
+++ test_images/drawing.svg 1970-01-01 00:00:00 +0000
@@ -1,118 +0,0 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!-- Created with Inkscape (http://www.inkscape.org/) -->
3
4<svg
5 xmlns:dc="http://purl.org/dc/elements/1.1/"
6 xmlns:cc="http://creativecommons.org/ns#"
7 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8 xmlns:svg="http://www.w3.org/2000/svg"
9 xmlns="http://www.w3.org/2000/svg"
10 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
11 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
12 width="744.09448819"
13 height="1052.3622047"
14 id="svg2"
15 version="1.1"
16 inkscape:version="0.47 r22583"
17 sodipodi:docname="New document 1">
18 <defs
19 id="defs4">
20 <marker
21 inkscape:stockid="Arrow1Lend"
22 orient="auto"
23 refY="0.0"
24 refX="0.0"
25 id="Arrow1Lend"
26 style="overflow:visible;">
27 <path
28 id="path3596"
29 d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
30 style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
31 transform="scale(0.8) rotate(180) translate(12.5,0)" />
32 </marker>
33 <marker
34 inkscape:stockid="Arrow1Lstart"
35 orient="auto"
36 refY="0.0"
37 refX="0.0"
38 id="Arrow1Lstart"
39 style="overflow:visible">
40 <path
41 id="path3593"
42 d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
43 style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
44 transform="scale(0.8) translate(12.5,0)" />
45 </marker>
46 <inkscape:perspective
47 sodipodi:type="inkscape:persp3d"
48 inkscape:vp_x="0 : 526.18109 : 1"
49 inkscape:vp_y="0 : 1000 : 0"
50 inkscape:vp_z="744.09448 : 526.18109 : 1"
51 inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
52 id="perspective10" />
53 </defs>
54 <sodipodi:namedview
55 id="base"
56 pagecolor="#ffffff"
57 bordercolor="#666666"
58 borderopacity="1.0"
59 inkscape:pageopacity="0.0"
60 inkscape:pageshadow="2"
61 inkscape:zoom="0.7"
62 inkscape:cx="257.79836"
63 inkscape:cy="623.94763"
64 inkscape:document-units="px"
65 inkscape:current-layer="layer1"
66 showgrid="false"
67 inkscape:window-width="1152"
68 inkscape:window-height="789"
69 inkscape:window-x="0"
70 inkscape:window-y="24"
71 inkscape:window-maximized="1" />
72 <metadata
73 id="metadata7">
74 <rdf:RDF>
75 <cc:Work
76 rdf:about="">
77 <dc:format>image/svg+xml</dc:format>
78 <dc:type
79 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
80 <dc:title></dc:title>
81 </cc:Work>
82 </rdf:RDF>
83 </metadata>
84 <g
85 inkscape:label="Layer 1"
86 inkscape:groupmode="layer"
87 id="layer1">
88 <path
89 style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart);marker-mid:none;marker-end:url(#Arrow1Lend)"
90 d="m 105.71429,146.6479 0,274.28571 246.42856,-0.71428"
91 id="path2816"
92 sodipodi:nodetypes="ccc" />
93 <path
94 style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
95 d="m 112.14286,263.07647 30,-32.85715 134.28571,170"
96 id="path4410" />
97 <text
98 xml:space="preserve"
99 style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
100 x="316.39716"
101 y="17.035498"
102 id="text4412"
103 transform="matrix(0.60856319,0.79350541,-0.79350541,0.60856319,0,0)"><tspan
104 sodipodi:role="line"
105 id="tspan4414"
106 x="316.39716"
107 y="17.035498"
108 style="font-size:11px">Calo delle vendite</tspan></text>
109 <path
110 style="fill:none;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
111 d="M 225.71429,592.36218 158.57143,756.6479 344.28571,713.79075"
112 id="path4416" />
113 <path
114 style="fill:none;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
115 d="m 198.57143,670.93361 54.28571,60"
116 id="path4418" />
117 </g>
118</svg>
1190
=== removed file 'test_images/roi.svg'
--- test_images/roi.svg 2010-07-03 00:05:02 +0000
+++ test_images/roi.svg 1970-01-01 00:00:00 +0000
@@ -1,170 +0,0 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!-- Created with Inkscape (http://www.inkscape.org/) -->
3
4<svg
5 xmlns:dc="http://purl.org/dc/elements/1.1/"
6 xmlns:cc="http://creativecommons.org/ns#"
7 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8 xmlns:svg="http://www.w3.org/2000/svg"
9 xmlns="http://www.w3.org/2000/svg"
10 xmlns:xlink="http://www.w3.org/1999/xlink"
11 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
12 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13 width="600"
14 height="300"
15 id="svg2"
16 version="1.1"
17 inkscape:version="0.47 r22583"
18 sodipodi:docname="roi.svg">
19 <defs
20 id="defs4">
21 <linearGradient
22 inkscape:collect="always"
23 id="linearGradient5711">
24 <stop
25 style="stop-color:#0000ff;stop-opacity:1;"
26 offset="0"
27 id="stop5713" />
28 <stop
29 style="stop-color:#0000ff;stop-opacity:0;"
30 offset="1"
31 id="stop5715" />
32 </linearGradient>
33 <inkscape:perspective
34 sodipodi:type="inkscape:persp3d"
35 inkscape:vp_x="0 : 526.18109 : 1"
36 inkscape:vp_y="0 : 1000 : 0"
37 inkscape:vp_z="744.09448 : 526.18109 : 1"
38 inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
39 id="perspective10" />
40 <linearGradient
41 inkscape:collect="always"
42 xlink:href="#linearGradient5711"
43 id="linearGradient5717"
44 x1="-0.5"
45 y1="902.36218"
46 x2="600.5"
47 y2="902.36218"
48 gradientUnits="userSpaceOnUse"
49 gradientTransform="matrix(0.99833752,0,0,0.99667503,0.49875296,-749.36182)" />
50 <inkscape:perspective
51 id="perspective3676"
52 inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
53 inkscape:vp_z="1 : 0.5 : 1"
54 inkscape:vp_y="0 : 1000 : 0"
55 inkscape:vp_x="0 : 0.5 : 1"
56 sodipodi:type="inkscape:persp3d" />
57 <inkscape:perspective
58 id="perspective3704"
59 inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
60 inkscape:vp_z="1 : 0.5 : 1"
61 inkscape:vp_y="0 : 1000 : 0"
62 inkscape:vp_x="0 : 0.5 : 1"
63 sodipodi:type="inkscape:persp3d" />
64 </defs>
65 <sodipodi:namedview
66 id="base"
67 pagecolor="#ffffff"
68 bordercolor="#666666"
69 borderopacity="1.0"
70 inkscape:pageopacity="0.0"
71 inkscape:pageshadow="2"
72 inkscape:zoom="1.3616667"
73 inkscape:cx="225.18656"
74 inkscape:cy="133.68434"
75 inkscape:document-units="px"
76 inkscape:current-layer="layer1"
77 showgrid="false"
78 inkscape:window-width="1280"
79 inkscape:window-height="949"
80 inkscape:window-x="0"
81 inkscape:window-y="24"
82 inkscape:window-maximized="1" />
83 <metadata
84 id="metadata7">
85 <rdf:RDF>
86 <cc:Work
87 rdf:about="">
88 <dc:format>image/svg+xml</dc:format>
89 <dc:type
90 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
91 <dc:title />
92 </cc:Work>
93 </rdf:RDF>
94 </metadata>
95 <metadata
96 id="a4-presentation-information">
97 {&quot;path&quot;:[&quot;one&quot;,&quot;two&quot;,&quot;three&quot;]}</metadata>
98 <g
99 inkscape:label="Layer 1"
100 inkscape:groupmode="layer"
101 id="layer1">
102 <rect
103 style="fill:url(#linearGradient5717);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.9975059;stroke-opacity:1"
104 id="all"
105 width="599.0025"
106 height="299.0025"
107 x="0.49875295"
108 y="0.49874461"
109 inkscape:label="#rect2816" />
110 <rect
111 style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:1.013;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
112 id="one"
113 width="198.9865"
114 height="98.986504"
115 x="50.506744"
116 y="50.506802"
117 inkscape:label="#rect5062" />
118 <rect
119 style="fill:#008000;fill-rule:evenodd;stroke:#000000;stroke-width:0.89774972px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
120 id="two"
121 width="149.10225"
122 height="99.102249"
123 x="171.85901"
124 y="323.65402"
125 transform="matrix(0.8660254,-0.5,0.5,0.8660254,0,0)"
126 inkscape:label="#rect2884" />
127 <text
128 xml:space="preserve"
129 style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans;font-stretch:normal;font-variant:normal"
130 x="116.66015"
131 y="110.56646"
132 id="text3658"><tspan
133 sodipodi:role="line"
134 x="116.66015"
135 y="110.56646"
136 id="tspan3662"
137 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans">one</tspan></text>
138 <text
139 xml:space="preserve"
140 style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
141 x="216.74605"
142 y="384.34283"
143 id="text3666"
144 transform="matrix(0.8660254,-0.5,0.5,0.8660254,0,0)"><tspan
145 sodipodi:role="line"
146 id="tspan3668"
147 x="216.74605"
148 y="384.34283">two</tspan></text>
149 <rect
150 style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.20260075999999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
151 id="three"
152 width="39.797398"
153 height="19.7974"
154 x="380.10132"
155 y="30.101299"
156 inkscape:label="#rect5062" />
157 <text
158 xml:space="preserve"
159 style="font-size:8.00003052px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
160 x="390.99463"
161 y="42.113239"
162 id="text3658-9"
163 transform="scale(0.99999871,1.0000013)"><tspan
164 sodipodi:role="line"
165 x="390.99463"
166 y="42.113239"
167 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
168 id="tspan3724">three</tspan></text>
169 </g>
170</svg>
1710
=== added directory 'tests'
=== renamed directory 'test_images' => 'tests/images'
=== added file 'tests/images/drawing.svg'
--- tests/images/drawing.svg 1970-01-01 00:00:00 +0000
+++ tests/images/drawing.svg 2010-07-14 09:01:45 +0000
@@ -0,0 +1,118 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!-- Created with Inkscape (http://www.inkscape.org/) -->
3
4<svg
5 xmlns:dc="http://purl.org/dc/elements/1.1/"
6 xmlns:cc="http://creativecommons.org/ns#"
7 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8 xmlns:svg="http://www.w3.org/2000/svg"
9 xmlns="http://www.w3.org/2000/svg"
10 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
11 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
12 width="744.09448819"
13 height="1052.3622047"
14 id="svg2"
15 version="1.1"
16 inkscape:version="0.47 r22583"
17 sodipodi:docname="New document 1">
18 <defs
19 id="defs4">
20 <marker
21 inkscape:stockid="Arrow1Lend"
22 orient="auto"
23 refY="0.0"
24 refX="0.0"
25 id="Arrow1Lend"
26 style="overflow:visible;">
27 <path
28 id="path3596"
29 d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
30 style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
31 transform="scale(0.8) rotate(180) translate(12.5,0)" />
32 </marker>
33 <marker
34 inkscape:stockid="Arrow1Lstart"
35 orient="auto"
36 refY="0.0"
37 refX="0.0"
38 id="Arrow1Lstart"
39 style="overflow:visible">
40 <path
41 id="path3593"
42 d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
43 style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
44 transform="scale(0.8) translate(12.5,0)" />
45 </marker>
46 <inkscape:perspective
47 sodipodi:type="inkscape:persp3d"
48 inkscape:vp_x="0 : 526.18109 : 1"
49 inkscape:vp_y="0 : 1000 : 0"
50 inkscape:vp_z="744.09448 : 526.18109 : 1"
51 inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
52 id="perspective10" />
53 </defs>
54 <sodipodi:namedview
55 id="base"
56 pagecolor="#ffffff"
57 bordercolor="#666666"
58 borderopacity="1.0"
59 inkscape:pageopacity="0.0"
60 inkscape:pageshadow="2"
61 inkscape:zoom="0.7"
62 inkscape:cx="257.79836"
63 inkscape:cy="623.94763"
64 inkscape:document-units="px"
65 inkscape:current-layer="layer1"
66 showgrid="false"
67 inkscape:window-width="1152"
68 inkscape:window-height="789"
69 inkscape:window-x="0"
70 inkscape:window-y="24"
71 inkscape:window-maximized="1" />
72 <metadata
73 id="metadata7">
74 <rdf:RDF>
75 <cc:Work
76 rdf:about="">
77 <dc:format>image/svg+xml</dc:format>
78 <dc:type
79 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
80 <dc:title></dc:title>
81 </cc:Work>
82 </rdf:RDF>
83 </metadata>
84 <g
85 inkscape:label="Layer 1"
86 inkscape:groupmode="layer"
87 id="layer1">
88 <path
89 style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart);marker-mid:none;marker-end:url(#Arrow1Lend)"
90 d="m 105.71429,146.6479 0,274.28571 246.42856,-0.71428"
91 id="path2816"
92 sodipodi:nodetypes="ccc" />
93 <path
94 style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
95 d="m 112.14286,263.07647 30,-32.85715 134.28571,170"
96 id="path4410" />
97 <text
98 xml:space="preserve"
99 style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
100 x="316.39716"
101 y="17.035498"
102 id="text4412"
103 transform="matrix(0.60856319,0.79350541,-0.79350541,0.60856319,0,0)"><tspan
104 sodipodi:role="line"
105 id="tspan4414"
106 x="316.39716"
107 y="17.035498"
108 style="font-size:11px">Calo delle vendite</tspan></text>
109 <path
110 style="fill:none;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
111 d="M 225.71429,592.36218 158.57143,756.6479 344.28571,713.79075"
112 id="path4416" />
113 <path
114 style="fill:none;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
115 d="m 198.57143,670.93361 54.28571,60"
116 id="path4418" />
117 </g>
118</svg>
0119
=== added file 'tests/images/roi.svg'
--- tests/images/roi.svg 1970-01-01 00:00:00 +0000
+++ tests/images/roi.svg 2010-07-14 09:01:45 +0000
@@ -0,0 +1,170 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!-- Created with Inkscape (http://www.inkscape.org/) -->
3
4<svg
5 xmlns:dc="http://purl.org/dc/elements/1.1/"
6 xmlns:cc="http://creativecommons.org/ns#"
7 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8 xmlns:svg="http://www.w3.org/2000/svg"
9 xmlns="http://www.w3.org/2000/svg"
10 xmlns:xlink="http://www.w3.org/1999/xlink"
11 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
12 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13 width="600"
14 height="300"
15 id="svg2"
16 version="1.1"
17 inkscape:version="0.47 r22583"
18 sodipodi:docname="roi.svg">
19 <defs
20 id="defs4">
21 <linearGradient
22 inkscape:collect="always"
23 id="linearGradient5711">
24 <stop
25 style="stop-color:#0000ff;stop-opacity:1;"
26 offset="0"
27 id="stop5713" />
28 <stop
29 style="stop-color:#0000ff;stop-opacity:0;"
30 offset="1"
31 id="stop5715" />
32 </linearGradient>
33 <inkscape:perspective
34 sodipodi:type="inkscape:persp3d"
35 inkscape:vp_x="0 : 526.18109 : 1"
36 inkscape:vp_y="0 : 1000 : 0"
37 inkscape:vp_z="744.09448 : 526.18109 : 1"
38 inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
39 id="perspective10" />
40 <linearGradient
41 inkscape:collect="always"
42 xlink:href="#linearGradient5711"
43 id="linearGradient5717"
44 x1="-0.5"
45 y1="902.36218"
46 x2="600.5"
47 y2="902.36218"
48 gradientUnits="userSpaceOnUse"
49 gradientTransform="matrix(0.99833752,0,0,0.99667503,0.49875296,-749.36182)" />
50 <inkscape:perspective
51 id="perspective3676"
52 inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
53 inkscape:vp_z="1 : 0.5 : 1"
54 inkscape:vp_y="0 : 1000 : 0"
55 inkscape:vp_x="0 : 0.5 : 1"
56 sodipodi:type="inkscape:persp3d" />
57 <inkscape:perspective
58 id="perspective3704"
59 inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
60 inkscape:vp_z="1 : 0.5 : 1"
61 inkscape:vp_y="0 : 1000 : 0"
62 inkscape:vp_x="0 : 0.5 : 1"
63 sodipodi:type="inkscape:persp3d" />
64 </defs>
65 <sodipodi:namedview
66 id="base"
67 pagecolor="#ffffff"
68 bordercolor="#666666"
69 borderopacity="1.0"
70 inkscape:pageopacity="0.0"
71 inkscape:pageshadow="2"
72 inkscape:zoom="1.3616667"
73 inkscape:cx="225.18656"
74 inkscape:cy="133.68434"
75 inkscape:document-units="px"
76 inkscape:current-layer="layer1"
77 showgrid="false"
78 inkscape:window-width="1280"
79 inkscape:window-height="949"
80 inkscape:window-x="0"
81 inkscape:window-y="24"
82 inkscape:window-maximized="1" />
83 <metadata
84 id="metadata7">
85 <rdf:RDF>
86 <cc:Work
87 rdf:about="">
88 <dc:format>image/svg+xml</dc:format>
89 <dc:type
90 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
91 <dc:title />
92 </cc:Work>
93 </rdf:RDF>
94 </metadata>
95 <metadata
96 id="a4-presentation-information">
97 {&quot;path&quot;:[&quot;one&quot;,&quot;two&quot;,&quot;three&quot;]}</metadata>
98 <g
99 inkscape:label="Layer 1"
100 inkscape:groupmode="layer"
101 id="layer1">
102 <rect
103 style="fill:url(#linearGradient5717);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.9975059;stroke-opacity:1"
104 id="all"
105 width="599.0025"
106 height="299.0025"
107 x="0.49875295"
108 y="0.49874461"
109 inkscape:label="#rect2816" />
110 <rect
111 style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:1.013;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
112 id="one"
113 width="198.9865"
114 height="98.986504"
115 x="50.506744"
116 y="50.506802"
117 inkscape:label="#rect5062" />
118 <rect
119 style="fill:#008000;fill-rule:evenodd;stroke:#000000;stroke-width:0.89774972px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
120 id="two"
121 width="149.10225"
122 height="99.102249"
123 x="171.85901"
124 y="323.65402"
125 transform="matrix(0.8660254,-0.5,0.5,0.8660254,0,0)"
126 inkscape:label="#rect2884" />
127 <text
128 xml:space="preserve"
129 style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans;font-stretch:normal;font-variant:normal"
130 x="116.66015"
131 y="110.56646"
132 id="text3658"><tspan
133 sodipodi:role="line"
134 x="116.66015"
135 y="110.56646"
136 id="tspan3662"
137 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans">one</tspan></text>
138 <text
139 xml:space="preserve"
140 style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
141 x="216.74605"
142 y="384.34283"
143 id="text3666"
144 transform="matrix(0.8660254,-0.5,0.5,0.8660254,0,0)"><tspan
145 sodipodi:role="line"
146 id="tspan3668"
147 x="216.74605"
148 y="384.34283">two</tspan></text>
149 <rect
150 style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.20260075999999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
151 id="three"
152 width="39.797398"
153 height="19.7974"
154 x="380.10132"
155 y="30.101299"
156 inkscape:label="#rect5062" />
157 <text
158 xml:space="preserve"
159 style="font-size:8.00003052px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
160 x="390.99463"
161 y="42.113239"
162 id="text3658-9"
163 transform="scale(0.99999871,1.0000013)"><tspan
164 sodipodi:role="line"
165 x="390.99463"
166 y="42.113239"
167 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
168 id="tspan3724">three</tspan></text>
169 </g>
170</svg>
0171
=== added file 'tests/opening_files.py'
--- tests/opening_files.py 1970-01-01 00:00:00 +0000
+++ tests/opening_files.py 2010-07-14 09:01:45 +0000
@@ -0,0 +1,39 @@
1# Copyright 2010 A4 Developers. This software is licensed under the
2# GNU General Public License version 3 (see the file COPYING).
3
4import os
5from unittest import TestCase
6from testhelpers import Application, TEST_IMAGE_FILE
7
8"""Try to open some files and see if A4 reports errors when it should."""
9
10
11class TestOpeningFiles(TestCase):
12 """Check that the procedure of opening a file works as expected."""
13
14 def test_open_existent_file(self):
15 """Try to open an existent file."""
16 app = Application(TEST_IMAGE_FILE)
17 self.assertRaises(AssertionError, app.wait_for, 'dlgError')
18
19 def test_open_inexistent_file(self):
20 """Try to open a file that doesn't exist."""
21 app = Application('this-file-does-not-exist')
22 # An error dialog should be shown saying that the file doesn't exist.
23 dialog = app.wait_for('dlgError')
24 message = dialog.gettextvalue('lblCannotopen*')
25 self.assertTrue(message.endswith('No such file or directory'))
26 dialog.click('btnClose')
27 del dialog
28
29 def test_open_incorrect_file(self):
30 """Try to open an existent file that is not a SVG image."""
31 # Open a Python script.
32 app = Application(os.path.abspath(__file__))
33 # An error dialog should be shown saying that the file format is
34 # incorrect.
35 dialog = app.wait_for('dlgError')
36 message = dialog.gettextvalue('lblCannotopen*')
37 self.assertTrue(message.endswith('Unknown file type'))
38 dialog.click('btnClose')
39 del dialog
040
=== added file 'tests/testhelpers.py'
--- tests/testhelpers.py 1970-01-01 00:00:00 +0000
+++ tests/testhelpers.py 2010-07-14 09:01:45 +0000
@@ -0,0 +1,67 @@
1# Copyright 2010 A4 Developers. This software is licensed under the
2# GNU General Public License version 3 (see the file COPYING).
3
4"""Helpers containing code common to almost every the test."""
5
6import os
7import ldtp
8
9# An image to be used for tests.
10TEST_IMAGE_FILE = os.path.abspath(
11 os.path.join(os.path.dirname(__file__), 'images', 'roi.svg'))
12
13# The default timeout for `waittillguiexist` and `waittillguinotexist`.
14_DEFAULT_TIMEOUT = 1
15
16
17class Window(object):
18 """An object representing a window or a message dialog."""
19
20 def __init__(self, window_id):
21 self.window_id = window_id
22 assert ldtp.waittillguiexist(window_id, guiTimeOut=_DEFAULT_TIMEOUT)
23
24 def __getattr__(self, attr_name):
25 """Return a wrapper around the LDTP method with the given name.
26
27 The returned wrapper is a function that automatically send the window
28 ID to the `ldtp` module.
29 """
30 ldtp_method = getattr(ldtp, attr_name)
31
32 def wrapper(*args, **kwargs):
33 retval = ldtp_method(self.window_id, *args, **kwargs)
34 if isinstance(retval, int):
35 assert retval
36 else:
37 return retval
38
39 return wrapper
40
41 def __del__(self):
42 """Wait for the closure of the window."""
43 # `window_id` may be unset if __init__ did not complete successfully.
44 if hasattr(self, 'window_id'):
45 ldtp.closewindow(self.window_id)
46 ldtp.waittillguinotexist(
47 self.window_id, guiTimeOut=_DEFAULT_TIMEOUT)
48
49 def __repr__(self):
50 return '<{0} {1!r}>'.format(self.__class__.__name__, self.window_id)
51
52
53class Application(Window):
54 """The main window of A4."""
55
56 def __init__(self, *args):
57 assert ldtp.launchapp('./a4', args)
58 super(Application, self).__init__('frmA4')
59
60 @property
61 def window_list(self):
62 """Return a list of IDs of the open windows, including this one."""
63 return ldtp.getwindowlist()
64
65 def wait_for(self, window_id):
66 """Wait for a window to be opened and return it's object."""
67 return Window(window_id)

Subscribers

People subscribed via source and target branches