1. Yuya Nishihara
  2. thg-qt-mq

Commits

Yuya Nishihara  committed 55b3b1a

wrinting functional tests

  • Participants
  • Parent commits 4946bd2
  • Branches default

Comments (0)

Files changed (5)

File backdoor.diff

View file
 # Date 1336279389 -32400
 # Branch stable
 # Node ID 39604ec2b6c2244e64441a58060357bfa1ca5947
-# Parent e97e9b6b22d9e80bd07376b8acdc7454ffdc3ecd
+# Parent 0574cf7d7941cee6a1a09fe765f890eca674177d
 tests: add helper extension and client to control running thg process
 
 It inclues tests/functional/thgbackdoor_test.py as a usage example.
 new file mode 100644
 --- /dev/null
 +++ b/contrib/thgbackdoor.py
-@@ -0,0 +1,230 @@
+@@ -0,0 +1,234 @@
 +# thgbackdoor.py - server to execute arbitrary code on TortoiseHg
 +#
 +# Copyright 2012 Yuya Nishihara <yuya@tcha.org>
 +http://stackoverflow.com/questions/2749655/
 +"""
 +import os, traceback
-+from PyQt4.QtCore import QByteArray, QCoreApplication, QObject, QTimer
++from PyQt4.QtCore import QByteArray, QObject, QTimer
 +from PyQt4.QtCore import Qt, pyqtSignal, pyqtSlot
++from PyQt4.QtGui import QApplication
 +from PyQt4.QtNetwork import QHostAddress, QTcpServer
 +from mercurial import demandimport
 +
 +        else:
 +            def runcode():
 +                exec code in self._context
-+            QTimer.singleShot(delay * 1000, runcode)
++            QTimer.singleShot(int(delay * 1000), runcode)
 +
 +    def _processquit(self):
 +        # postpone to next event loop so that response message can be sent
-+        QTimer.singleShot(0, QCoreApplication.quit)
++        def quitgracefully():
++            QApplication.closeAllWindows()
++            QApplication.quit()  # in case quitOnLastWindowClosed is False
++        QTimer.singleShot(0, quitgracefully)
 +
 +    _reqtable = {
 +        'eval': _processeval,
 new file mode 100644
 --- /dev/null
 +++ b/tests/functional/__init__.py
-@@ -0,0 +1,1 @@
-+"""Functional tests of thg application"""
+@@ -0,0 +1,7 @@
++"""Test functionality of the application by actually running it"""
++from nose.plugins.skip import SkipTest
++from PyQt4.QtGui import QApplication
++
++def setup():
++    if QApplication.type() != QApplication.GuiClient:
++        raise SkipTest
 diff --git a/tests/functional/thgbackdoor_test.py b/tests/functional/thgbackdoor_test.py
 new file mode 100644
 --- /dev/null
 +++ b/tests/functional/thgbackdoor_test.py
-@@ -0,0 +1,61 @@
+@@ -0,0 +1,62 @@
 +"""Test basic functionality of thgbackdoor extension and ThgClient"""
 +import os, socket, time, unittest
 +from nose.tools import *
 +        QTest.keyClick(dlg, "N", Qt.ControlModifier)
 +        ''', delay=0)
 +        # introduce a helper function?
-+        for _i in xrange(1):
++        for _i in xrange(5):
 +            time.sleep(0.1)
-+            aw = self.thg.eval('QApplication.activeWindow().__class__.__name__')
++            aw = self.thg.eval('QApplication.activeModalWidget()'
++                               '.__class__.__name__')
 +            if aw == 'InitDialog':
 +                break
 +        else:
  try:
      import cStringIO as StringIO
  except ImportError:
-@@ -151,3 +155,213 @@ class HgClient(object):
+@@ -151,3 +155,219 @@ class HgClient(object):
          if path.startswith('/'):
              raise ValueError('not a relative path: %s' % path)
          return os.path.join(self.path, path)
 +        else:
 +            raise ValueError('unexpected message: %r' % msg)
 +
++    def gettimeout(self):
++        return self._timeout
++
 +    def settimeout(self, sec):
 +        self._timeout = sec
 +        if self._sock:
 +    def homedir(self):
 +        return self._homedir
 +
++    @property
++    def configdir(self):
++        return os.path.join(self._homedir, '.config')
++
 +    def open(self):
 +        if self._proc:
 +            raise ValueError('already open')
 +        finally:
 +            f.close()
 +
-+        configdir = os.path.join(self._homedir, '.config')
-+        if not os.path.exists(configdir):
-+            os.mkdir(configdir)
++        if not os.path.exists(self.configdir):
++            os.mkdir(self.configdir)
 +
 +        env = os.environ.copy()
 +        env['HOME'] = self._homedir
 +        env['HGRCPATH'] = newhgrc
-+        env['APPDATA'] = env['XDG_CONFIG_HOME'] = configdir
++        env['APPDATA'] = env['XDG_CONFIG_HOME'] = self.configdir
 +        env['THGBACKDOOR'] = '%s:%d' % self._address
 +        env['QT4_IM_MODULE'] = env['QT_IM_MODULE'] = ''  # suppress warning
 +
 +    """Start thg process and return object to control it
 +
 +    :cmdargs: extra arguments to be passed to thg
-+    :homedir: switch HOME and APPDATA (default: fresh temporary directory)
++    :homedir: switch HOME (default: fresh temporary directory)
 +    """
 +    thg = ThgClient(('localhost', port), cmdargs=cmdargs, homedir=homedir,
 +                    timeout=timeout)
 diff --git a/tests/run-tests.py b/tests/run-tests.py
 --- a/tests/run-tests.py
 +++ b/tests/run-tests.py
-@@ -5,6 +5,10 @@ To run all tests::
+@@ -5,6 +5,19 @@ To run all tests::
  
      % HGPATH=path/to/mercurial ./run-tests.py
  
 +
 +    % HGPATH=path/to/mercurial ./run-tests.py -e functional
 +
++To run without X display::
++
++    % HGPATH=path/to/mercurial xvfb-run ./run-tests.py
++
++or on separate X display::
++
++    % Xephyr :3 &
++    % DISPLAY=:3 HGPATH=path/to/mercurial xvfb-run ./run-tests.py
++
  For details, please see:
  
  - `./run-tests.py --help`

File qsettings.diff

View file
 # HG changeset patch
-# Parent b9556ffd2323eb2b08ada68545ac9c88f44f96a5
-tests: setup consistent directory for QSettings
+# Parent f0cce13a1e4ca879e7462ec7d6b32fb524b565a3
+tests: setup consistent place to store QSettings
 
 diff --git a/tests/nosehgenv.py b/tests/nosehgenv.py
 --- a/tests/nosehgenv.py
          # instances will lead crash.
          self._qapp = QApplication([])
  
-+        # settings will be stored at $HGTMP/.config/TortoiseHg/TortoiseHgQt.ini
++        # settings will be saved at $HGTMP/.config/TortoiseHg/TortoiseHgQt.ini
 +        self._qapp.setApplicationName('TortoiseHgQt')
 +        self._qapp.setOrganizationName('TortoiseHg')
 +        QSettings.setDefaultFormat(QSettings.IniFormat)

File series

View file
 tests-gui.diff
 backdoor.diff
 test-workbench-sess.diff
+thgcli-qsettings.diff
 sync-pushpull-check.mbox
 graftdialog.patch
 mani-iconisnull.diff

File test-workbench-sess.diff

View file
 # HG changeset patch
-# Parent 10c43a9201f4025eb8d9f006d059c69f281099b5
+# Parent eb7a53e66b36b3db9c156dede88c97e8bf40e934
+tests: test basic functionality of workbench session restore
 
 diff --git a/tests/functional/workbench_session_test.py b/tests/functional/workbench_session_test.py
 new file mode 100644
 --- /dev/null
 +++ b/tests/functional/workbench_session_test.py
-@@ -0,0 +1,36 @@
-+"""Test for workbench session"""
-+import os, unittest
+@@ -0,0 +1,34 @@
++"""Test save/restore of workbench session"""
++import os
++from nose.tools import *
 +
 +import helpers
 +
-+class WorkbenchSessionTest(unittest.TestCase):
-+    @classmethod
-+    def setUpClass(cls):
-+        cls.tmpdir = helpers.mktmpdir('%s.%s' % (__name__, cls.__name__))
-+        # XXX
-+        os.makedirs(os.path.join(cls.tmpdir, '.config', 'TortoiseHg'))
-+        f = open(os.path.join(cls.tmpdir, '.config', 'TortoiseHg', 'TortoiseHgQt.ini'), 'w')
-+        try:
-+            f.write('[Workbench]\n')
-+            f.write('saveRepos=true\n')
-+        finally:
-+            f.close()
++_repos = ('foo', 'bar', 'baz')
 +
-+        for name in ('foo', 'bar', 'baz'):
-+            helpers.HgClient(os.path.join(cls.tmpdir, name)).init()
++def setup():
++    global _tmpdir
++    _tmpdir = helpers.mktmpdir(__name__)
 +
-+    def setUp(self):
-+        self.thg = helpers.openthg(homedir=self.tmpdir)
++    for name in _repos:
++        helpers.HgClient(os.path.join(_tmpdir, name)).init()
 +
-+    def tearDown(self):
-+        self.thg.close()
++def test_save_restore():
++    thg = helpers.openthg(homedir=_tmpdir)
++    try:
++        thg.exec_('QTest.qWaitForWindowShown(dlg)')
++        thg.exec_('dlg.actionSaveRepos.setChecked(True)')
++        for name in _repos:
++            thg.exec_('dlg.openRepo("%s", reuse=False)' % name)
++        thg.exec_('dlg.repoTabsWidget.setCurrentIndex(1)')
++    finally:
++        thg.close()
 +
-+    def test_xxx(self):
-+        #self.thg.exec_('QTest.qWaitForWindowShown(dlg)')
-+        for name in ('foo', 'bar', 'baz'):
-+            self.thg.exec_('dlg.openRepo("%s", reuse=False)' % name)
-+        self.thg.exec_('dlg.repoTabsWidget.setCurrentIndex(1)')
-+        self.assertEqual(3, self.thg.eval('dlg.repoTabsWidget.count()'))
-+
-+        self.thg.exec_('dlg.close()')  # XXX
-+        # XXX
++    thg = helpers.openthg(homedir=_tmpdir)
++    try:
++        thg.exec_('QTest.qWaitForWindowShown(dlg)')
++        assert_equals(3, thg.eval('dlg.repoTabsWidget.count()'))
++        currepo = thg.eval('dlg.repoTabsWidget.currentWidget().repo.root')
++        assert_equals('bar', os.path.basename(currepo))
++    finally:
++        thg.close()

File thgcli-qsettings.diff

View file
+# HG changeset patch
+# Parent 5f849b13eb8eb499a1e9f61d2c3e1ab8983933dd
+tests: add convenient method to access QSettings of running process
+
+XXX seems not usable
+
+diff --git a/tests/helpers.py b/tests/helpers.py
+--- a/tests/helpers.py
++++ b/tests/helpers.py
+@@ -9,7 +9,7 @@ try:
+ except ImportError:
+     import StringIO
+ from nose import tools
+-from PyQt4.QtCore import QTextCodec
++from PyQt4.QtCore import QSettings, QTextCodec
+ from mercurial import dispatch, encoding as encodingmod, ui as uimod
+ from tortoisehg.util import hglib
+ 
+@@ -306,6 +306,11 @@ class ThgClient(object):
+     def configdir(self):
+         return os.path.join(self._homedir, '.config')
+ 
++    def qsettings(self):
++        return QSettings(os.path.join(self.configdir, 'TortoiseHg',
++                                      'TortoiseHgQt.ini'),
++                         QSettings.IniFormat)
++
+     def open(self):
+         if self._proc:
+             raise ValueError('already open')