Back to index

apport  2.3
test_ui_kde.py
Go to the documentation of this file.
00001 '''KDE 4 Apport User Interface tests'''
00002 
00003 # Copyright (C) 2012 Canonical Ltd.
00004 # Author: Evan Dandrea <evan.dandrea@canonical.com>
00005 #
00006 # This program is free software; you can redistribute it and/or modify it
00007 # under the terms of the GNU General Public License as published by the
00008 # Free Software Foundation; either version 2 of the License, or (at your
00009 # option) any later version.  See http://www.gnu.org/copyleft/gpl.html for
00010 # the full text of the license.
00011 import imp
00012 import unittest
00013 import tempfile
00014 import sys
00015 import os
00016 import shutil
00017 
00018 from mock import patch
00019 from PyQt4.QtCore import QTimer, QCoreApplication
00020 from PyQt4.QtGui import QTreeWidget
00021 from PyKDE4.kdecore import ki18n, KCmdLineArgs, KAboutData, KLocalizedString
00022 from PyKDE4.kdeui import KApplication
00023 
00024 import apport
00025 from apport import unicode_gettext as _
00026 import apport.crashdb_impl.memory
00027 
00028 if os.environ.get('APPORT_TEST_LOCAL'):
00029     apport_kde_path = 'kde/apport-kde'
00030 else:
00031     apport_kde_path = os.path.join(os.environ.get('APPORT_DATA_DIR', '/usr/share/apport'), 'apport-kde')
00032 MainUserInterface = imp.load_source('', apport_kde_path).MainUserInterface
00033 
00034 # Work around MainUserInterface using basename to find the KDE UI file.
00035 sys.argv[0] = apport_kde_path
00036 
00037 
00038 class T(unittest.TestCase):
00039     @classmethod
00040     def setUpClass(klass):
00041         r = apport.Report()
00042         r.add_os_info()
00043         klass.distro = r['DistroRelease']
00044 
00045     def setUp(self):
00046         self.report_dir = tempfile.mkdtemp()
00047         apport.fileutils.report_dir = self.report_dir
00048         os.environ['APPORT_REPORT_DIR'] = self.report_dir
00049         # do not cause eternal hangs because of error dialog boxes
00050         os.environ['APPORT_DISABLE_DISTRO_CHECK'] = '1'
00051 
00052         self.app = MainUserInterface()
00053 
00054         # use in-memory crashdb
00055         self.app.crashdb = apport.crashdb_impl.memory.CrashDatabase(None, {})
00056 
00057         # disable package hooks, as they might ask for sudo password and other
00058         # interactive bits; allow tests to install their own hooks
00059         self.hook_dir = tempfile.mkdtemp()
00060         apport.report._hook_dir = self.hook_dir
00061         apport.report._common_hook_dir = self.hook_dir
00062 
00063         # test report
00064         self.app.report_file = os.path.join(self.report_dir, 'bash.crash')
00065 
00066         self.app.report = apport.Report()
00067         self.app.report['ExecutablePath'] = '/bin/bash'
00068         self.app.report['Signal'] = '11'
00069         self.app.report['CoreDump'] = b'\x01\x02'
00070         with open(self.app.report_file, 'wb') as f:
00071             self.app.report.write(f)
00072 
00073     def tearDown(self):
00074         if self.app.dialog:
00075             QCoreApplication.processEvents()
00076             self.app.dialog.done(0)
00077             QCoreApplication.processEvents()
00078 
00079         shutil.rmtree(self.report_dir)
00080         shutil.rmtree(self.hook_dir)
00081 
00082     def test_close_button(self):
00083         '''Clicking the close button on the window does not report the crash.'''
00084 
00085         def c(*args):
00086             self.app.dialog.reject()
00087         QTimer.singleShot(0, c)
00088         result = self.app.ui_present_report_details(True)
00089         self.assertFalse(result['report'])
00090 
00091     def test_kernel_crash_layout(self):
00092         '''
00093         +-----------------------------------------------------------------+
00094         | [ logo ] YourDistro has experienced an internal error.          |
00095         |                                                                 |
00096         |            [x] Send an error report to help fix this problem.   |
00097         |                                                                 |
00098         | [ Show Details ]                                   [ Continue ] |
00099         +-----------------------------------------------------------------+
00100         '''
00101         self.app.report['ProblemType'] = 'KernelCrash'
00102         QTimer.singleShot(0, QCoreApplication.quit)
00103         self.app.ui_present_report_details(True)
00104         self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0])
00105         self.assertEqual(self.app.dialog.heading.text(),
00106                          _('Sorry, %s has experienced an internal error.') % self.distro)
00107         self.assertTrue(self.app.dialog.send_error_report.isVisible())
00108         self.assertTrue(self.app.dialog.send_error_report.isChecked())
00109         self.assertTrue(self.app.dialog.details.isVisible())
00110         self.assertTrue(self.app.dialog.continue_button.isVisible())
00111         self.assertEqual(self.app.dialog.continue_button.text(), _('Continue'))
00112         self.assertFalse(self.app.dialog.closed_button.isVisible())
00113         self.assertFalse(self.app.dialog.text.isVisible())
00114 
00115     def test_package_crash_layout(self):
00116         '''
00117         +-----------------------------------------------------------------+
00118         | [ error  ] Sorry, a problem occurred while installing software. |
00119         |            Package: apport 1.2.3~0ubuntu1                       |
00120         |                                                                 |
00121         |            [x] Send an error report to help fix this problem.   |
00122         |                                                                 |
00123         | [ Show Details ]                                   [ Continue ] |
00124         +-----------------------------------------------------------------+
00125         '''
00126         self.app.report['ProblemType'] = 'Package'
00127         self.app.report['Package'] = 'apport 1.2.3~0ubuntu1'
00128         QTimer.singleShot(0, QCoreApplication.quit)
00129         self.app.ui_present_report_details(True)
00130         self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0])
00131         self.assertEqual(self.app.dialog.heading.text(),
00132                          _('Sorry, a problem occurred while installing software.'))
00133         self.assertTrue(self.app.dialog.send_error_report.isVisible())
00134         self.assertTrue(self.app.dialog.send_error_report.isChecked())
00135         self.assertTrue(self.app.dialog.details.isVisible())
00136         self.assertTrue(self.app.dialog.continue_button.isVisible())
00137         self.assertEqual(self.app.dialog.continue_button.text(), _('Continue'))
00138         self.assertFalse(self.app.dialog.closed_button.isVisible())
00139         self.assertEqual(self.app.dialog.text.text(),
00140                          _('Package: apport 1.2.3~0ubuntu1'))
00141 
00142     def test_regular_crash_layout(self):
00143         '''
00144         +-----------------------------------------------------------------+
00145         | [ apport ] The application Apport has closed unexpectedly.      |
00146         |                                                                 |
00147         |            [x] Send an error report to help fix this problem.   |
00148         |            [ ] Ignore future problems of this program version.  |
00149         |                                                                 |
00150         | [ Show Details ]                                   [ Continue ] |
00151         +-----------------------------------------------------------------+
00152         '''
00153         self.app.report['ProblemType'] = 'Crash'
00154         self.app.report['CrashCounter'] = '1'
00155         self.app.report['Package'] = 'apport 1.2.3~0ubuntu1'
00156         with tempfile.NamedTemporaryFile() as fp:
00157             fp.write(b'''[Desktop Entry]
00158 Version=1.0
00159 Name=Apport
00160 Type=Application''')
00161             fp.flush()
00162             self.app.report['DesktopFile'] = fp.name
00163             QTimer.singleShot(0, QCoreApplication.quit)
00164             self.app.ui_present_report_details(True)
00165         self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0])
00166         self.assertEqual(self.app.dialog.heading.text(),
00167                          _('The application Apport has closed unexpectedly.'))
00168         self.assertTrue(self.app.dialog.send_error_report.isVisible())
00169         self.assertTrue(self.app.dialog.send_error_report.isChecked())
00170         self.assertTrue(self.app.dialog.details.isVisible())
00171         # no ProcCmdline, cannot restart
00172         self.assertTrue(self.app.dialog.continue_button.isVisible())
00173         self.assertEqual(self.app.dialog.continue_button.text(), _('Continue'))
00174         self.assertFalse(self.app.dialog.closed_button.isVisible())
00175         self.assertFalse(self.app.dialog.text.isVisible())
00176         self.assertFalse(self.app.dialog.text.isVisible())
00177         self.assertTrue(self.app.dialog.ignore_future_problems.isVisible())
00178         self.assertTrue(str(self.app.dialog.ignore_future_problems.text()).endswith(
00179             'of this program version'))
00180 
00181     def test_regular_crash_layout_restart(self):
00182         '''
00183         +-----------------------------------------------------------------+
00184         | [ apport ] The application Apport has closed unexpectedly.      |
00185         |                                                                 |
00186         |            [x] Send an error report to help fix this problem.   |
00187         |            [ ] Ignore future problems of this program version.  |
00188         |                                                                 |
00189         | [ Show Details ]                 [ Leave Closed ]  [ Relaunch ] |
00190         +-----------------------------------------------------------------+
00191         '''
00192         self.app.report['ProblemType'] = 'Crash'
00193         self.app.report['CrashCounter'] = '1'
00194         self.app.report['ProcCmdline'] = 'apport-bug apport'
00195         self.app.report['Package'] = 'apport 1.2.3~0ubuntu1'
00196         with tempfile.NamedTemporaryFile() as fp:
00197             fp.write(b'''[Desktop Entry]
00198 Version=1.0
00199 Name=Apport
00200 Type=Application''')
00201             fp.flush()
00202             self.app.report['DesktopFile'] = fp.name
00203             QTimer.singleShot(0, QCoreApplication.quit)
00204             self.app.ui_present_report_details(True)
00205         self.assertEqual(self.app.dialog.windowTitle(),
00206                          self.distro.split()[0])
00207         self.assertEqual(self.app.dialog.heading.text(),
00208                          _('The application Apport has closed unexpectedly.'))
00209         self.assertTrue(self.app.dialog.send_error_report.isVisible())
00210         self.assertTrue(self.app.dialog.send_error_report.isChecked())
00211         self.assertTrue(self.app.dialog.details.isVisible())
00212         self.assertTrue(self.app.dialog.continue_button.isVisible())
00213         self.assertEqual(self.app.dialog.continue_button.text(), _('Relaunch'))
00214         self.assertTrue(self.app.dialog.closed_button.isVisible())
00215         self.assertFalse(self.app.dialog.text.isVisible())
00216         self.assertFalse(self.app.dialog.text.isVisible())
00217         self.assertTrue(self.app.dialog.ignore_future_problems.isVisible())
00218         self.assertTrue(str(self.app.dialog.ignore_future_problems.text()).endswith(
00219             'of this program version'))
00220 
00221     def test_system_crash_layout(self):
00222         '''
00223         +-----------------------------------------------------------------+
00224         | [ logo ] Sorry, YourDistro has experienced an internal error.   |
00225         |            If you notice further problems, try restarting the   |
00226         |            computer                                             |
00227         |                                                                 |
00228         |            [x] Send an error report to help fix this problem.   |
00229         |            [ ] Ignore future problems of this type.             |
00230         |                                                                 |
00231         | [ Show Details ]                                   [ Continue ] |
00232         +-----------------------------------------------------------------+
00233         '''
00234         self.app.report['ProblemType'] = 'Crash'
00235         self.app.report['CrashCounter'] = '1'
00236         self.app.report['Package'] = 'apport 1.2.3~0ubuntu1'
00237         QTimer.singleShot(0, QCoreApplication.quit)
00238         self.app.ui_present_report_details(True)
00239         self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0])
00240         self.assertEqual(self.app.dialog.heading.text(),
00241                          _('Sorry, %s has experienced an internal error.') % self.distro)
00242         self.assertEqual(self.app.dialog.text.text(),
00243                          _('If you notice further problems, try restarting the computer.'))
00244         self.assertTrue(self.app.dialog.text.isVisible())
00245         self.assertTrue(self.app.dialog.send_error_report.isVisible())
00246         self.assertTrue(self.app.dialog.send_error_report.isChecked())
00247         self.assertTrue(self.app.dialog.details.isVisible())
00248         self.assertTrue(self.app.dialog.continue_button.isVisible())
00249         self.assertEqual(self.app.dialog.continue_button.text(), _('Continue'))
00250         self.assertFalse(self.app.dialog.closed_button.isVisible())
00251         self.assertTrue(self.app.dialog.ignore_future_problems.isVisible())
00252         self.assertTrue(str(self.app.dialog.ignore_future_problems.text()).endswith(
00253             'of this type'))
00254 
00255     def test_apport_bug_package_layout(self):
00256         '''
00257         +-------------------------------------------------------------------+
00258         | [ error  ] Send problem report to the developers?                 |
00259         |                                                                   |
00260         |            +----------------------------------------------------+ |
00261         |            | |> ApportVersion                                   | |
00262         |            | ...                                                | |
00263         |            +----------------------------------------------------+ |
00264         |                                                                   |
00265         | [ Cancel ]                                               [ Send ] |
00266         +-------------------------------------------------------------------+
00267         '''
00268         self.app.report_file = None
00269         QTimer.singleShot(0, QCoreApplication.quit)
00270         self.app.ui_present_report_details(True)
00271         self.assertEqual(self.app.dialog.windowTitle(), self.distro.split()[0])
00272         self.assertEqual(self.app.dialog.heading.text(),
00273                          _('Send problem report to the developers?'))
00274         self.assertFalse(self.app.dialog.text.isVisible())
00275         self.assertFalse(self.app.dialog.send_error_report.isVisible())
00276         self.assertTrue(self.app.dialog.send_error_report.isChecked())
00277         self.assertFalse(self.app.dialog.details.isVisible())
00278         self.assertTrue(self.app.dialog.continue_button.isVisible())
00279         self.assertEqual(self.app.dialog.continue_button.text(), _('Send'))
00280         self.assertFalse(self.app.dialog.closed_button.isVisible())
00281         self.assertTrue(self.app.dialog.cancel_button.isVisible())
00282         self.assertTrue(self.app.dialog.treeview.isVisible())
00283 
00284     @patch.object(MainUserInterface, 'open_url')
00285     def test_1_crash_nodetails(self, *args):
00286         '''Crash report without showing details'''
00287 
00288         self.visible_progress = None
00289 
00290         def cont(*args):
00291             if self.app.dialog and self.app.dialog.continue_button.isVisible():
00292                 self.app.dialog.continue_button.click()
00293                 QTimer.singleShot(500, check_progress)
00294                 return
00295             # try again
00296             QTimer.singleShot(1000, cont)
00297 
00298         def check_progress(*args):
00299             self.visible_progress = (self.app.progress is not None)
00300 
00301         QTimer.singleShot(1000, cont)
00302         self.app.run_crash(self.app.report_file)
00303 
00304         # we should have reported one crash
00305         self.assertEqual(self.app.crashdb.latest_id(), 0)
00306         r = self.app.crashdb.download(0)
00307         self.assertEqual(r['ProblemType'], 'Crash')
00308         self.assertEqual(r['ExecutablePath'], '/bin/bash')
00309 
00310         # should show a progress bar for info collection
00311         self.assertEqual(self.visible_progress, True)
00312 
00313         # data was collected
00314         self.assertTrue(r['Package'].startswith('bash '))
00315         self.assertTrue('libc' in r['Dependencies'])
00316         self.assertTrue('Stacktrace' in r)
00317 
00318         # URL was opened
00319         self.assertEqual(self.app.open_url.call_count, 1)
00320 
00321     @patch.object(MainUserInterface, 'open_url')
00322     def test_1_crash_details(self, *args):
00323         '''Crash report with showing details'''
00324 
00325         self.visible_progress = None
00326 
00327         def show_details(*args):
00328             if self.app.dialog and self.app.dialog.show_details.isVisible():
00329                 self.app.dialog.show_details.click()
00330                 QTimer.singleShot(1000, cont)
00331                 return
00332 
00333             # try again
00334             QTimer.singleShot(200, show_details)
00335 
00336         def cont(*args):
00337             # wait until data collection is done and tree filled
00338             details = self.app.dialog.findChild(QTreeWidget, 'details')
00339             if details.topLevelItemCount() == 0:
00340                 QTimer.singleShot(200, cont)
00341                 return
00342 
00343             if self.app.dialog and self.app.dialog.continue_button.isVisible():
00344                 self.app.dialog.continue_button.click()
00345                 QTimer.singleShot(500, check_progress)
00346                 return
00347             # try again
00348             QTimer.singleShot(200, cont)
00349 
00350         def check_progress(*args):
00351             self.visible_progress = (self.app.progress is not None)
00352 
00353         QTimer.singleShot(200, show_details)
00354         self.app.run_crash(self.app.report_file)
00355 
00356         # we should have reported one crash
00357         self.assertEqual(self.app.crashdb.latest_id(), 0)
00358         r = self.app.crashdb.download(0)
00359         self.assertEqual(r['ProblemType'], 'Crash')
00360         self.assertEqual(r['ExecutablePath'], '/bin/bash')
00361 
00362         # we already collected details, do not show the progress dialog again
00363         self.assertFalse(self.visible_progress)
00364 
00365         # data was collected
00366         self.assertTrue(r['Package'].startswith('bash '))
00367         self.assertTrue('libc' in r['Dependencies'])
00368         self.assertTrue('Stacktrace' in r)
00369 
00370         # URL was opened
00371         self.assertEqual(self.app.open_url.call_count, 1)
00372 
00373     @patch.object(MainUserInterface, 'open_url')
00374     def test_1_crash_noaccept(self, *args):
00375         '''Crash report with non-accepting crash DB'''
00376 
00377         self.visible_progress = None
00378 
00379         def cont(*args):
00380             if self.app.dialog and self.app.dialog.continue_button.isVisible():
00381                 self.app.dialog.continue_button.click()
00382                 QTimer.singleShot(500, check_progress)
00383                 return
00384             # try again
00385             QTimer.singleShot(1000, cont)
00386 
00387         def check_progress(*args):
00388             self.visible_progress = (self.app.progress is not None)
00389 
00390         QTimer.singleShot(1000, cont)
00391         self.app.crashdb.options['problem_types'] = ['bug']
00392         self.app.run_crash(self.app.report_file)
00393 
00394         # we should not have reported the crash
00395         self.assertEqual(self.app.crashdb.latest_id(), -1)
00396         self.assertEqual(self.app.open_url.call_count, 0)
00397 
00398         # no progress dialog for non-accepting DB
00399         self.assertEqual(self.visible_progress, False)
00400 
00401         # data was collected for whoopsie
00402         r = self.app.report
00403         self.assertEqual(r['ProblemType'], 'Crash')
00404         self.assertEqual(r['ExecutablePath'], '/bin/bash')
00405         self.assertTrue(r['Package'].startswith('bash '))
00406         self.assertTrue('libc' in r['Dependencies'])
00407         self.assertTrue('Stacktrace' in r)
00408 
00409     def test_bug_report_installed_package(self):
00410         '''Bug report for installed package'''
00411 
00412         self.app.report_file = None
00413         self.app.options.package = 'bash'
00414 
00415         def c(*args):
00416             if self.app.dialog and self.app.dialog.cancel_button.isVisible():
00417                 self.app.dialog.cancel_button.click()
00418                 return
00419             # try again
00420             QTimer.singleShot(1000, c)
00421 
00422         QTimer.singleShot(1000, c)
00423         self.app.run_report_bug()
00424 
00425         self.assertEqual(self.app.report['ProblemType'], 'Bug')
00426         self.assertEqual(self.app.report['SourcePackage'], 'bash')
00427         self.assertTrue(self.app.report['Package'].startswith('bash '))
00428         self.assertNotEqual(self.app.report['Dependencies'], '')
00429 
00430     def test_bug_report_uninstalled_package(self):
00431         '''Bug report for uninstalled package'''
00432 
00433         pkg = apport.packaging.get_uninstalled_package()
00434 
00435         self.app.report_file = None
00436         self.app.options.package = pkg
00437 
00438         def c(*args):
00439             if self.app.dialog and self.app.dialog.cancel_button.isVisible():
00440                 self.app.dialog.cancel_button.click()
00441                 return
00442             # try again
00443             QTimer.singleShot(1000, c)
00444 
00445         QTimer.singleShot(1000, c)
00446         self.app.run_report_bug()
00447 
00448         self.assertEqual(self.app.report['ProblemType'], 'Bug')
00449         self.assertEqual(self.app.report['SourcePackage'],
00450                          apport.packaging.get_source(pkg))
00451         self.assertEqual(self.app.report['Package'], '%s (not installed)' % pkg)
00452 
00453     @patch.object(MainUserInterface, 'open_url')
00454     def test_1_update_report(self, *args):
00455         '''Updating an existing report'''
00456 
00457         self.app.report_file = None
00458 
00459         def cont(*args):
00460             if self.app.dialog and self.app.dialog.continue_button.isVisible():
00461                 self.app.dialog.continue_button.click()
00462                 return
00463             # try again
00464             QTimer.singleShot(200, cont)
00465 
00466         # upload empty report
00467         id = self.app.crashdb.upload({})
00468         self.assertEqual(id, 0)
00469         self.app.options.update_report = 0
00470         self.app.options.package = 'bash'
00471 
00472         QTimer.singleShot(200, cont)
00473         self.app.run_update_report()
00474 
00475         # no new bug reported
00476         self.assertEqual(self.app.crashdb.latest_id(), 0)
00477 
00478         # bug was updated
00479         r = self.app.crashdb.download(0)
00480         self.assertTrue(r['Package'].startswith('bash '))
00481         self.assertTrue('libc' in r['Dependencies'])
00482         self.assertTrue('DistroRelease' in r)
00483 
00484         # No URL in this mode
00485         self.assertEqual(self.app.open_url.call_count, 0)
00486 
00487     @patch.object(MainUserInterface, 'open_url')
00488     def test_1_update_report_different_binary_source(self, *args):
00489         '''Updating an existing report on a source package which does not have a binary of the same name'''
00490 
00491         self.app.report_file = None
00492 
00493         def cont(*args):
00494             if self.app.dialog and self.app.dialog.continue_button.isVisible():
00495                 self.app.dialog.continue_button.click()
00496                 return
00497             # try again
00498             QTimer.singleShot(200, cont)
00499 
00500         kernel_pkg = apport.packaging.get_kernel_package()
00501         kernel_src = apport.packaging.get_source(kernel_pkg)
00502         self.assertNotEqual(kernel_pkg, kernel_src,
00503                             'this test assumes that the kernel binary package != kernel source package')
00504         self.assertNotEqual(apport.packaging.get_version(kernel_pkg), '',
00505                             'this test assumes that the kernel binary package %s is installed' % kernel_pkg)
00506         # this test assumes that the kernel source package name is not an
00507         # installed binary package
00508         self.assertRaises(ValueError, apport.packaging.get_version, kernel_src)
00509 
00510         # create source package hook, as otherwise there is nothing to collect
00511         with open(os.path.join(self.hook_dir, 'source_%s.py' % kernel_src), 'w') as f:
00512             f.write('def add_info(r, ui):\n r["MachineType"]="Laptop"\n')
00513 
00514         # upload empty report
00515         id = self.app.crashdb.upload({})
00516         self.assertEqual(id, 0)
00517 
00518         # run in update mode for that bug
00519         self.app.options.update_report = 0
00520         self.app.options.package = kernel_src
00521 
00522         QTimer.singleShot(200, cont)
00523         self.app.run_update_report()
00524 
00525         # no new bug reported
00526         self.assertEqual(self.app.crashdb.latest_id(), 0)
00527 
00528         # bug was updated
00529         r = self.app.crashdb.download(0)
00530         self.assertTrue('ProcEnviron' in r)
00531         self.assertTrue('DistroRelease' in r)
00532         self.assertTrue('Uname' in r)
00533         self.assertEqual(r['MachineType'], 'Laptop')
00534 
00535         # No URL in this mode
00536         self.assertEqual(self.app.open_url.call_count, 0)
00537 
00538     def test_administrator_disabled_reporting(self):
00539         QTimer.singleShot(0, QCoreApplication.quit)
00540         self.app.ui_present_report_details(False)
00541         self.assertFalse(self.app.dialog.send_error_report.isVisible())
00542         self.assertFalse(self.app.dialog.send_error_report.isChecked())
00543 
00544 appName = 'apport-kde'
00545 catalog = 'apport'
00546 programName = ki18n(b'Apport KDE')
00547 version = '1.0'
00548 description = ki18n(b'KDE 4 frontend tests for the apport')
00549 license = KAboutData.License_GPL
00550 copyright = ki18n(b'2012 Canonical Ltd.')
00551 text = KLocalizedString()
00552 homePage = 'https://wiki.ubuntu.com/AutomatedProblemReports'
00553 bugEmail = 'kubuntu-devel@lists.ubuntu.com'
00554 
00555 aboutData = KAboutData(appName, catalog, programName, version, description,
00556                        license, copyright, text, homePage, bugEmail)
00557 
00558 KCmdLineArgs.init([''], aboutData)
00559 app = KApplication()
00560 unittest.main()