示例#1
0
 def testLoadFromNamesInvalidCaseNames(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames(
                                  "suitespkg1.suitesmdl11.Suite111.case1111",
                                  "suitespkg2.suitesmdl22.Suite221.case2213")
     self.failUnlessEqual(len(tests), 1)
     self.failUnless(errors)
示例#2
0
 def testLoadFromNamesInvalidCaseNames(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames(
         "suitespkg1.suitesmdl11.Suite111.case1111",
         "suitespkg2.suitesmdl22.Suite221.case2213")
     self.failUnlessEqual(len(tests), 1)
     self.failUnless(errors)
示例#3
0
 def testLoadTreeInvalidMdlName(self):
     loader = TestLoader()
     tree, errors = loader.loadTree("suitespkg1.suitesmdl13")
     self.failUnlessEqual(len(tree), 1)
     self.failUnless("suitespkg1" in tree)
     self.failIf(tree["suitespkg1"][None])
     self.failUnless(errors)
示例#4
0
 def testLoadTreeInvalidMdlName(self):
     loader = TestLoader()
     tree, errors = loader.loadTree("suitespkg1.suitesmdl13")
     self.failUnlessEqual(len(tree), 1)
     self.failUnless("suitespkg1" in tree)
     self.failIf(tree["suitespkg1"][None])
     self.failUnless(errors)
示例#5
0
 def testLoadFromNamesCaseNames(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames(
         "suitespkg1.suitesmdl11.Suite111.case1111",
         "suitespkg1.suitesmdl11.Suite112.case1122",
         "suitespkg2.suitesmdl22.Suite221.case2211")
     self.failUnlessEqual(len(tests), 3)
     self.failIf(errors)
示例#6
0
 def testLoadFromNamesMixedNames(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames("suitespkg2.suitesmdl21",
                                  "suitespkg1.suitesmdl11.Suite111.case1112",
                                  "suitespkg1.suitesmdl11.Suite111",
                                  "suitespkg2.suitesmdl21.Suite212.case2121")
     self.failUnlessEqual(len(tests), 3)
     self.failIf(errors)
示例#7
0
 def testLoadFromNamesCaseNamesOfSameSuite(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames(
                                  "suitespkg1.suitesmdl11.Suite111.case1111",
                                  "suitespkg1.suitesmdl11.Suite111.case1112")
     self.failUnlessEqual(len(tests), 1)
     self.failUnlessEqual(len([case for case in tests[0]]), 2)
     self.failIf(errors)
示例#8
0
 def testLoadFromNamesCaseNamesOfSameSuite(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames(
         "suitespkg1.suitesmdl11.Suite111.case1111",
         "suitespkg1.suitesmdl11.Suite111.case1112")
     self.failUnlessEqual(len(tests), 1)
     self.failUnlessEqual(len([case for case in tests[0]]), 2)
     self.failIf(errors)
示例#9
0
 def testLoadTreeSuiteName(self):
     loader = TestLoader()
     tree, errors = loader.loadTree("suitespkg1.suitesmdl12.Suite121")
     self.failUnlessEqual(len(tree), 1)
     self.failUnless("suitespkg1" in tree)
     self.failUnlessEqual(len(tree["suitespkg1"]), 1)
     self.failUnless("suitesmdl12" in tree["suitespkg1"])
     self.failUnlessEqual(len(tree["suitespkg1"]["suitesmdl12"][None]), 1)
     self.failIf(errors)
示例#10
0
 def testLoadTree(self):
     loader = TestLoader()
     tree, errors = loader.loadTree()
     self.failUnless(len(tree) >= 2)
     for name in ("suitespkg1", "suitespkg2"):
         self.failUnless(name in tree)
         branch = tree[name]
         self.failUnless(len(branch) >= 3)
     self.failIf(errors)
示例#11
0
 def testLoadFromNamesSuitesWithBaseClass(self):
     loader = TestLoader()
     tree, errors = loader.loadTree("suitespkg2.suitesmdl22")
     self.failUnlessEqual(len(tree), 1)
     self.failUnless("suitespkg2" in tree)
     self.failUnlessEqual(len(tree["suitespkg2"]), 1)
     self.failUnless("suitesmdl22" in tree["suitespkg2"])
     self.failUnlessEqual(len(tree["suitespkg2"]["suitesmdl22"][None]), 3)
     self.failIf(errors)
示例#12
0
 def testLoadFromNamesSimilarNames(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames(
                              "suitespkg2.suitesmdl21.Suite211.case2111",
                              "suitespkg2.suitesmdl21.Suite211.case21112",
                              "suitespkg2.suitesmdl21.Suite211.case211111")
     self.failUnlessEqual(len(tests), 1)
     self.failUnlessEqual(len([case for case in tests[0]]), 3)
     self.failIf(errors)
示例#13
0
 def testLoadTree(self):
     loader = TestLoader()
     tree, errors = loader.loadTree()
     self.failUnless(len(tree) >= 2)
     for name in ("suitespkg1", "suitespkg2"):
         self.failUnless(name in tree)
         branch = tree[name]
         self.failUnless(len(branch) >= 3)
     self.failIf(errors)
示例#14
0
 def testLoadFromNamesSimilarNames(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames(
         "suitespkg2.suitesmdl21.Suite211.case2111",
         "suitespkg2.suitesmdl21.Suite211.case21112",
         "suitespkg2.suitesmdl21.Suite211.case211111")
     self.failUnlessEqual(len(tests), 1)
     self.failUnlessEqual(len([case for case in tests[0]]), 3)
     self.failIf(errors)
示例#15
0
 def testLoadFromNamesSameNames(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames(
         "suitespkg1.suitesmdl12.Suite121", "suitespkg1.suitesmdl12.",
         "suitespkg1.suitesmdl12.Suite122",
         "suitespkg1.suitesmdl12.Suite121",
         "suitespkg1.suitesmdl12.Suite121.case1212")
     self.failUnlessEqual(len(tests), 2)
     self.failIf(errors)
示例#16
0
 def testLoadTreeSuiteName(self):
     loader = TestLoader()
     tree, errors = loader.loadTree("suitespkg1.suitesmdl12.Suite121")
     self.failUnlessEqual(len(tree), 1)
     self.failUnless("suitespkg1" in tree)
     self.failUnlessEqual(len(tree["suitespkg1"]), 1)
     self.failUnless("suitesmdl12" in tree["suitespkg1"])
     self.failUnlessEqual(len(tree["suitespkg1"]["suitesmdl12"][None]), 1)
     self.failIf(errors)
示例#17
0
 def testLoadFromNamesSuitesWithBaseClass(self):
     loader = TestLoader()
     tree, errors = loader.loadTree("suitespkg2.suitesmdl22")
     self.failUnlessEqual(len(tree), 1)
     self.failUnless("suitespkg2" in tree)
     self.failUnlessEqual(len(tree["suitespkg2"]), 1)
     self.failUnless("suitesmdl22" in tree["suitespkg2"])
     self.failUnlessEqual(len(tree["suitespkg2"]["suitesmdl22"][None]), 3)
     self.failIf(errors)
示例#18
0
 def testLoadFromNamesSameNames(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames(
                              "suitespkg1.suitesmdl12.Suite121",
                              "suitespkg1.suitesmdl12.",
                              "suitespkg1.suitesmdl12.Suite122",
                              "suitespkg1.suitesmdl12.Suite121",
                              "suitespkg1.suitesmdl12.Suite121.case1212")
     self.failUnlessEqual(len(tests), 2)
     self.failIf(errors)
示例#19
0
 def __init__(self, locsTree, testsTree, modelsTree):
     '''
     Takes trees for locations, tests and models, initializes a test
     loader instance and loads default paths from configuration.
     '''
     QtCore.QObject.__init__(self)
     self._locsTree = locsTree
     self._testsTree = testsTree
     self._modelsTree = modelsTree
     self._locsTree.itemChanged.connect(self._updateLocations)
     self._testsTree.itemChanged.connect(self._updateCheckboxes)
     self._loader = TestLoader()
     self._loaded = False
     self._locItems = {}
     self.loadState()
示例#20
0
def runTestCases(tests, locations, devices):
    '''
    A function responsible for running the given test cases.
    '''
    log.debug("Run test cases from '%s' locations using '%s' devices: %s"
               % (", ".join(locations), ", ".join([str(d) for d in devices]),
                  ", ".join(tests)))
    loader = TestLoader()
    amountToRun = 0
    for path in locations:
        location.add(path)
    if not isinstance(tests, (list, tuple)):
        tests = [tests]
    suites, errors = loader.loadFromNames(*tests)

    ncases = 0
    for test in suites:
        ncases += test.count()
    print (" LOADED %d TEST CASES " % ncases).center(80, '-') + '\n'

    if len(errors) > 0:
        print "There were errors during loading test cases:"
        for error in errors:
            print "%s\n%s" % (error.name, error.traceback)
            printSeparator()
        print

    if not ncases:
        #Nothing to do
        exitWithStatus(status=0)

    log.info("Start running tests: %s" % suites)
    channels.add("SummaryChannel", SUMMARY_CHANNEL)
    result = testresult.TestResult()
    runner = TestRunner(devices, suites, result)

    for device in devices:
        device.connect()
    try:
        runner.start()
        runner.join()
    except KeyboardInterrupt:
        runner.stop()
    finally:
        for device in devices:
            if device.isConnected():
                device.disconnect()
    return result
示例#21
0
文件: tests.py 项目: mlyko/tadek-ui
 def __init__(self, locsTree, testsTree, modelsTree):
     '''
     Takes trees for locations, tests and models, initializes a test
     loader instance and loads default paths from configuration.
     '''
     QtCore.QObject.__init__(self)
     self._locsTree = locsTree
     self._testsTree = testsTree
     self._modelsTree = modelsTree
     self._locsTree.itemChanged.connect(self._updateLocations)
     self._testsTree.itemChanged.connect(self._updateCheckboxes)
     self._loader = TestLoader()
     self._loaded = False
     self._locItems = {}
     self.loadState()
示例#22
0
class Tests(QtCore.QObject):
    '''
    Class for management of locations list, tests tree and models tree.
    '''
    _TESTCASES_DIR = "testcases"

    _CONFIG_NAME = viewName()
    _CONFIG_SECTION_LOCATIONS = "locations"
    _expandOnRefresh = settings.get(_CONFIG_NAME,
                                    "options",
                                    "expand_on_refresh",
                                    default="No",
                                    force=True)

    _ICONS = {
        "directory": QtGui.QIcon(":/test/icons/folder-grey.png"),
        "module": QtGui.QIcon(":/test/icons/text-x-python.png"),
        "suite": QtGui.QIcon(":/test/icons/source_moc.png"),
        "case": QtGui.QIcon(":/test/icons/inode-blockdevice.png")
    }

    def __init__(self, locsTree, testsTree, modelsTree):
        '''
        Takes trees for locations, tests and models, initializes a test
        loader instance and loads default paths from configuration.
        '''
        QtCore.QObject.__init__(self)
        self._locsTree = locsTree
        self._testsTree = testsTree
        self._modelsTree = modelsTree
        self._locsTree.itemChanged.connect(self._updateLocations)
        self._testsTree.itemChanged.connect(self._updateCheckboxes)
        self._loader = TestLoader()
        self._loaded = False
        self._locItems = {}
        self.loadState()

# Private methods:

    def _addLocation(self, path):
        '''
        Adds a location and a corresponding item to the locations tree.
        Returns None on success or an error message on failure.
        '''
        if path in self._locItems:
            return
        location.add(path, enabled=False)
        item = QtGui.QTreeWidgetItem()
        item.setText(0, path)
        item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable
                      | QtCore.Qt.ItemIsSelectable)
        item.setCheckState(0, QtCore.Qt.Unchecked)
        self._locsTree.addTopLevelItem(item)
        self._locsTree.resizeColumnToContents(0)
        self._locItems[path] = item

    def _changeExpansionState(self, state, selected=True):
        '''
        Manipulates expansion states of items in the tests tree. If selected is
        True (default), then only selected items are affected.
        '''
        def expandWithChildren(item, state):
            item.setExpanded(state)
            for i in xrange(item.childCount()):
                expandWithChildren(item.child(i), state)

        if selected:
            for item in self._testsTree.selectedItems():
                expandWithChildren(item, state)
        else:
            for i in xrange(self._testsTree.topLevelItemCount()):
                expandWithChildren(self._testsTree.topLevelItem(i), state)
        self._testsTree.resizeColumnToContents(0)

    def _updateModels(self):
        '''
        Refreshes the models tree.
        '''
        self._modelsTree.clear()
        for name, path in location.getModels().iteritems():
            QtGui.QTreeWidgetItem(self._modelsTree, [name, path])
        self._modelsTree.resizeColumnToContents(0)
        self._modelsTree.resizeColumnToContents(1)

# Slots:
#@QtCore.Slot()

    def addLocation(self):
        '''
        Adds an item to locations tree and enables it. A warning is displayed
        if path is invalid.
        '''
        path = QtGui.QFileDialog.getExistingDirectory(window())
        if not path:
            return
        log.debug("Adding test path '%s'" % path)
        message = self._addLocation(path)
        if message is not None:
            runWarning(message)
            return
        self._locItems[path].setCheckState(0, QtCore.Qt.Checked)

    #@QtCore.Slot()
    def removeLocation(self):
        '''
        Removes selected items from locations tree and refreshes
        the tests tree.
        '''
        items = self._locsTree.selectedItems()
        if not (items and runQuestion(
                "Are you sure you want to remove %s?\n\n %s" %
            ("these locations" if len(items) > 1 else "this location",
             "\n".join(item.text(0) for item in items)))):
            return
        for item in items:
            path = item.text(0)
            log.debug("Removing test path '%s'" % path)
            location.remove(path)
            self._locsTree.takeTopLevelItem(
                self._locsTree.indexOfTopLevelItem(item))
            self._locItems.pop(path)
        self.refresh()

    #@QtCore.Slot()
    def getCheckedTests(self):
        '''
        Loads checked tests cases and returns them in a list on success
        or None on failure.
        '''
        def findCheckedNames(tests, item):
            if item.checkState(0) == QtCore.Qt.Checked:
                tests.append(item.testName)
                return
            elif item.checkState(0) == QtCore.Qt.PartiallyChecked:
                for i in xrange(item.childCount()):
                    findCheckedNames(tests, item.child(i))

        names = []
        for i in xrange(self._testsTree.topLevelItemCount()):
            findCheckedNames(names, self._testsTree.topLevelItem(i))
        if not names:
            runWarning("Select some test cases first")
            return names
        tests, errors = self._loader.loadFromNames(*names)
        if errors:
            if self._loaded:
                dialog = LoadingErrorDialog(
                    "Errors occurred while loading "
                    "test cases", errors)
                dialog.run()
                return []

        return tests

    #@QtCore.Slot()
    def refresh(self):
        '''
        Clears and fills the tests tree and the models tree with contents from
        currently enabled locations.
        '''
        def makeItem(parent):
            item = TestItem(parent)
            item.setFlags(QtCore.Qt.ItemIsEnabled
                          | QtCore.Qt.ItemIsUserCheckable
                          | QtCore.Qt.ItemIsSelectable)
            item.setCheckState(0, QtCore.Qt.Unchecked)
            return item

        def buildSuite(name, suite, parent):
            item = makeItem(parent)
            item.setText(
                0, name if name is not None else suite.__class__.__name__)
            item.testName = ".".join((item.parent().testName, item.text(0)))
            if isinstance(suite, TestSuite):
                item.setIcon(0, self._ICONS["suite"])
                for name, childSuite in suite:
                    buildSuite(name, childSuite, item)
            elif isinstance(suite, TestCase):
                item.setIcon(0, self._ICONS["case"])
            else:
                raise TypeError()

        def buildTree(tree, parent):
            for key in sorted(tree):
                value = tree[key]
                if key is None and isinstance(value, list):
                    if not value and len(tree) == 1:
                        if parent.parent() is not None:
                            parent.parent().removeChild(parent)
                        else:
                            self._testsTree.takeTopLevelItem(
                                self._testsTree.indexOfTopLevelItem(parent))
                        continue
                    suite = None
                    for suite in value:
                        buildSuite(None, suite, parent)
                    if value:
                        r = suite.result()
                        if os.path.split(r.path)[1] != r.id.split(".")[-2]:
                            parent.setIcon(0, self._ICONS["module"])
                elif isinstance(value, dict):
                    item = makeItem(parent)
                    item.setText(0, key)
                    item.setIcon(0, self._ICONS["directory"])
                    item.testName = (".".join(
                        (item.parent().testName,
                         key)) if item.parent() is not None else key)
                    buildTree(value, item)

        self._testsTree.clear()
        tree, errors = self._loader.loadTree()
        if errors:
            if self._loaded:
                dialog = LoadingErrorDialog(
                    "Errors occurred while loading "
                    "test cases", errors)
                dialog.run()
        buildTree(tree, self._testsTree)
        self._testsTree.resizeColumnToContents(0)
        if self._expandOnRefresh.getBool():
            self.expandAll()
        self._updateModels()

    #@QtCore.Slot()
    def expandSelected(self):
        '''
        Expands selected test items including all descendants.
        '''
        self._changeExpansionState(state=True, selected=True)

    #@QtCore.Slot()
    def expandAll(self):
        '''
        Expands all test items including all descendants.
        '''
        self._changeExpansionState(state=True, selected=False)

    #@QtCore.Slot()
    def collapseSelected(self):
        '''
        Collapses selected test items including all descendants.
        '''
        self._changeExpansionState(state=False, selected=True)

    #@QtCore.Slot()
    def collapseAll(self):
        '''
        Collapses all test items including all descendants.
        '''
        self._changeExpansionState(state=False, selected=False)

    #@QtCore.Slot(QtGui.QTreeWidgetItem, int)
    def _updateLocations(self, item, column):
        '''
        Enables or disables a location and refreshes the tests tree.
        '''
        if item.checkState(0) == QtCore.Qt.Checked:
            errors = location.enable(item.text(0))
            if errors:
                if self._loaded:
                    dialog = LoadingErrorDialog(
                        "Errors occurred while enabling"
                        " a location", errors)
                    dialog.run()
                item.setCheckState(0, QtCore.Qt.Unchecked)
                return
        else:
            location.disable(item.text(0))
        self.refresh()

    #@QtCore.Slot(TestItem, int)
    def _updateCheckboxes(self, item, column):
        '''
        Updates states of check boxes in the tests tree in three-state manner. 
        '''
        def updateChildren(item, state):
            item.setCheckState(0, state)
            for i in xrange(item.childCount()):
                updateChildren(item.child(i), state)

        if item is not self._testsTree.currentItem():
            return
        updateChildren(item, item.checkState(0))
        parent = item.parent()
        while parent is not None:
            states = [
                parent.child(i).checkState(0)
                for i in xrange(parent.childCount())
            ]
            if (len(filter(lambda s: s == QtCore.Qt.Checked,
                           states)) == len(states)):
                state = QtCore.Qt.Checked
            elif (len(filter(lambda s: s == QtCore.Qt.Unchecked,
                             states)) == len(states)):
                state = QtCore.Qt.Unchecked
            else:
                state = QtCore.Qt.PartiallyChecked
            parent.setCheckState(0, state)
            parent = parent.parent()

# Public methods:

    def saveState(self):
        '''
        Saves paths to configuration.
        '''
        config.set(self._CONFIG_NAME, self._CONFIG_SECTION_LOCATIONS,
                   "enabled", location.get(enabled=True))
        config.set(self._CONFIG_NAME, self._CONFIG_SECTION_LOCATIONS,
                   "disabled", location.get(enabled=False))

    def loadState(self):
        '''
        Restores paths from configuration.
        '''
        enabled = config.getList(self._CONFIG_NAME,
                                 self._CONFIG_SECTION_LOCATIONS, "enabled", [])
        disabled = config.getList(self._CONFIG_NAME,
                                  self._CONFIG_SECTION_LOCATIONS, "disabled",
                                  [])
        for path in disabled:
            message = self._addLocation(path)
            if message:
                log.warning(message)
        for path in enabled:
            message = self._addLocation(path)
            if message:
                log.warning(message)
            else:
                self._locItems[path].setCheckState(0, QtCore.Qt.Checked)
        self._loaded = True
示例#23
0
 def testLoadFromNames(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames()
     self.failUnless(tests)
     self.failIf(errors)
示例#24
0
 def testLoadFromNamesInvalidClassName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames("suitespkg1.suitesmdl11.Suite113")
     self.failIf(tests)
     self.failUnless(errors)
示例#25
0
 def testLoadFromNamesInvalidMdlName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames("suitespkg2.suitesmdl29")
     self.failIf(tests)
     self.failUnless(errors)
示例#26
0
 def testLoadFromNamesPkgName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames("suitespkg1")
     self.failUnlessEqual(len(tests), 4)
     self.failIf(errors)
示例#27
0
 def testLoadTreeInvalidPkgName(self):
     loader = TestLoader()
     tree, errors = loader.loadTree("suitespkg99")
     self.failIf(tree)
     self.failUnless(errors)
示例#28
0
 def testLoadFromNamesInvalidCaseName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames(
                                 "suitespkg2.suitesmdl22.Suite221.case2213")
     self.failIf(tests)
     self.failUnless(errors)
示例#29
0
 def testLoadFromNamesPkgName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames("suitespkg1")
     self.failUnlessEqual(len(tests), 4)
     self.failIf(errors)
示例#30
0
 def testLoadTreeInvalidPkgName(self):
     loader = TestLoader()
     tree, errors = loader.loadTree("suitespkg99")
     self.failIf(tree)
     self.failUnless(errors)
示例#31
0
 def testLoadFromNamesMdlName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames("suitespkg2.suitesmdl21")
     self.failUnlessEqual(len(tests), 2)
     self.failIf(errors)
示例#32
0
 def testLoadFromNamesInvalidMdlName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames("suitespkg2.suitesmdl29")
     self.failIf(tests)
     self.failUnless(errors)
示例#33
0
 def testLoadFromNames(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames()
     self.failUnless(tests)
     self.failIf(errors)
示例#34
0
 def testLoadFromNamesClassName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames("suitespkg1.suitesmdl11.Suite112")
     self.failUnlessEqual(len(tests), 1)
     self.failIf(errors)
示例#35
0
 def testLoadFromNamesMdlName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames("suitespkg2.suitesmdl21")
     self.failUnlessEqual(len(tests), 2)
     self.failIf(errors)
示例#36
0
 def testLoadFromNamesInvalidClassName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames("suitespkg1.suitesmdl11.Suite113")
     self.failIf(tests)
     self.failUnless(errors)
示例#37
0
 def testLoadFromNamesClassName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames("suitespkg1.suitesmdl11.Suite112")
     self.failUnlessEqual(len(tests), 1)
     self.failIf(errors)
示例#38
0
 def testLoadFromNamesCaseName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames(
                                 "suitespkg2.suitesmdl22.Suite221.case2211")
     self.failUnlessEqual(len(tests), 1)
     self.failIf(errors)
示例#39
0
 def testLoadFromNamesInvalidCaseName(self):
     loader = TestLoader()
     tests, errors = loader.loadFromNames(
         "suitespkg2.suitesmdl22.Suite221.case2213")
     self.failIf(tests)
     self.failUnless(errors)
示例#40
0
文件: tests.py 项目: mlyko/tadek-ui
class Tests(QtCore.QObject):
    '''
    Class for management of locations list, tests tree and models tree.
    '''
    _TESTCASES_DIR = "testcases"

    _CONFIG_NAME = viewName()
    _CONFIG_SECTION_LOCATIONS = "locations"
    _expandOnRefresh = settings.get(_CONFIG_NAME, "options",
                                    "expand_on_refresh", default="No",
                                    force=True)

    _ICONS = {
        "directory": QtGui.QIcon(":/test/icons/folder-grey.png"),
        "module":    QtGui.QIcon(":/test/icons/text-x-python.png"),
        "suite":     QtGui.QIcon(":/test/icons/source_moc.png"),
        "case":      QtGui.QIcon(":/test/icons/inode-blockdevice.png")
    }

    def __init__(self, locsTree, testsTree, modelsTree):
        '''
        Takes trees for locations, tests and models, initializes a test
        loader instance and loads default paths from configuration.
        '''
        QtCore.QObject.__init__(self)
        self._locsTree = locsTree
        self._testsTree = testsTree
        self._modelsTree = modelsTree
        self._locsTree.itemChanged.connect(self._updateLocations)
        self._testsTree.itemChanged.connect(self._updateCheckboxes)
        self._loader = TestLoader()
        self._loaded = False
        self._locItems = {}
        self.loadState()

# Private methods:
    def _addLocation(self, path):
        '''
        Adds a location and a corresponding item to the locations tree.
        Returns None on success or an error message on failure.
        '''
        if path in self._locItems:
            return
        location.add(path, enabled=False)
        item = QtGui.QTreeWidgetItem()
        item.setText(0, path)
        item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable |
                      QtCore.Qt.ItemIsSelectable)
        item.setCheckState(0, QtCore.Qt.Unchecked)
        self._locsTree.addTopLevelItem(item)
        self._locsTree.resizeColumnToContents(0)
        self._locItems[path] = item

    def _changeExpansionState(self, state, selected=True):
        '''
        Manipulates expansion states of items in the tests tree. If selected is
        True (default), then only selected items are affected.
        '''
        def expandWithChildren(item, state):
            item.setExpanded(state)
            for i in xrange(item.childCount()):
                expandWithChildren(item.child(i), state)

        if selected:
            for item in self._testsTree.selectedItems():              
                expandWithChildren(item, state)
        else:
            for i in xrange(self._testsTree.topLevelItemCount()): 
                expandWithChildren(self._testsTree.topLevelItem(i), state)
        self._testsTree.resizeColumnToContents(0)

    def _updateModels(self):
        '''
        Refreshes the models tree.
        '''
        self._modelsTree.clear()
        for name, path in location.getModels().iteritems():
            QtGui.QTreeWidgetItem(self._modelsTree, [name, path])
        self._modelsTree.resizeColumnToContents(0)
        self._modelsTree.resizeColumnToContents(1)

# Slots:
    #@QtCore.Slot()
    def addLocation(self):
        '''
        Adds an item to locations tree and enables it. A warning is displayed
        if path is invalid.
        '''
        path = QtGui.QFileDialog.getExistingDirectory(window())
        if not path:
            return
        log.debug("Adding test path '%s'" % path)
        message = self._addLocation(path)
        if message is not None:
            runWarning(message)
            return
        self._locItems[path].setCheckState(0, QtCore.Qt.Checked)

    #@QtCore.Slot()
    def removeLocation(self):
        '''
        Removes selected items from locations tree and refreshes
        the tests tree.
        '''
        items = self._locsTree.selectedItems()
        if not (items and 
                runQuestion("Are you sure you want to remove %s?\n\n %s"
                            % ("these locations" if len(items) > 1
                                                 else "this location",
                               "\n".join(item.text(0) for item in items)))):
            return
        for item in items:
            path = item.text(0)
            log.debug("Removing test path '%s'" % path)
            location.remove(path)
            self._locsTree.takeTopLevelItem(
                self._locsTree.indexOfTopLevelItem(item))
            self._locItems.pop(path)
        self.refresh()

    #@QtCore.Slot()
    def getCheckedTests(self):
        '''
        Loads checked tests cases and returns them in a list on success
        or None on failure.
        '''
        def findCheckedNames(tests, item):
            if item.checkState(0) == QtCore.Qt.Checked:
                tests.append(item.testName)
                return
            elif item.checkState(0) == QtCore.Qt.PartiallyChecked:
                for i in xrange(item.childCount()):
                    findCheckedNames(tests, item.child(i))
        
        names = []
        for i in xrange(self._testsTree.topLevelItemCount()):
            findCheckedNames(names, self._testsTree.topLevelItem(i))
        if not names:
            runWarning("Select some test cases first")
            return names
        tests, errors = self._loader.loadFromNames(*names)
        if errors:
            if self._loaded:
                dialog = LoadingErrorDialog("Errors occurred while loading "
                                            "test cases", errors)
                dialog.run()
                return []

        return tests

    #@QtCore.Slot()
    def refresh(self):
        '''
        Clears and fills the tests tree and the models tree with contents from
        currently enabled locations.
        '''
        def makeItem(parent):
            item = TestItem(parent)
            item.setFlags(QtCore.Qt.ItemIsEnabled |
                          QtCore.Qt.ItemIsUserCheckable |
                          QtCore.Qt.ItemIsSelectable)
            item.setCheckState(0, QtCore.Qt.Unchecked)
            return item

        def buildSuite(name, suite, parent):
            item = makeItem(parent)
            item.setText(0,
                         name if name is not None else suite.__class__.__name__)
            item.testName = ".".join((item.parent().testName, item.text(0)))
            if isinstance(suite, TestSuite):
                item.setIcon(0, self._ICONS["suite"])
                for name, childSuite in suite:
                    buildSuite(name, childSuite, item)
            elif isinstance(suite, TestCase):
                item.setIcon(0, self._ICONS["case"])
            else:
                raise TypeError()

        def buildTree(tree, parent):
            for key in sorted(tree):
                value = tree[key]
                if key is None and isinstance(value, list):
                    if not value and len(tree) == 1:
                        if parent.parent() is not None:
                            parent.parent().removeChild(parent)
                        else:
                            self._testsTree.takeTopLevelItem(
                                self._testsTree.indexOfTopLevelItem(parent))
                        continue
                    suite = None
                    for suite in value:
                        buildSuite(None, suite, parent)
                    if value:
                        r = suite.result()
                        if os.path.split(r.path)[1] != r.id.split(".")[-2]:
                            parent.setIcon(0, self._ICONS["module"])
                elif isinstance(value, dict):
                    item = makeItem(parent)
                    item.setText(0, key)
                    item.setIcon(0, self._ICONS["directory"])
                    item.testName = (".".join((item.parent().testName, key))
                                      if item.parent() is not None else key)
                    buildTree(value, item)

        self._testsTree.clear()
        tree, errors = self._loader.loadTree()
        if errors:
            if self._loaded:
                dialog = LoadingErrorDialog("Errors occurred while loading "
                                            "test cases", errors)
                dialog.run()
        buildTree(tree, self._testsTree)
        self._testsTree.resizeColumnToContents(0)
        if self._expandOnRefresh.getBool():
            self.expandAll()
        self._updateModels()

    #@QtCore.Slot()
    def expandSelected(self):
        '''
        Expands selected test items including all descendants.
        '''
        self._changeExpansionState(state=True, selected=True)

    #@QtCore.Slot()
    def expandAll(self):
        '''
        Expands all test items including all descendants.
        '''
        self._changeExpansionState(state=True, selected=False)

    #@QtCore.Slot()
    def collapseSelected(self):
        '''
        Collapses selected test items including all descendants.
        '''
        self._changeExpansionState(state=False, selected=True)

    #@QtCore.Slot()
    def collapseAll(self):
        '''
        Collapses all test items including all descendants.
        '''
        self._changeExpansionState(state=False, selected=False)

    #@QtCore.Slot(QtGui.QTreeWidgetItem, int)
    def _updateLocations(self, item, column):
        '''
        Enables or disables a location and refreshes the tests tree.
        '''
        if item.checkState(0) == QtCore.Qt.Checked:
            errors = location.enable(item.text(0))
            if errors:
                if self._loaded:
                    dialog = LoadingErrorDialog("Errors occurred while enabling"
                                                " a location", errors)
                    dialog.run()
                item.setCheckState(0, QtCore.Qt.Unchecked)
                return
        else:
            location.disable(item.text(0))
        self.refresh()

    #@QtCore.Slot(TestItem, int)
    def _updateCheckboxes(self, item, column):
        '''
        Updates states of check boxes in the tests tree in three-state manner. 
        '''
        def updateChildren(item, state):
            item.setCheckState(0, state)
            for i in xrange(item.childCount()):
                updateChildren(item.child(i), state)

        if item is not self._testsTree.currentItem():
            return
        updateChildren(item, item.checkState(0))
        parent = item.parent()
        while parent is not None:
            states = [parent.child(i).checkState(0)
                      for i in xrange(parent.childCount())]
            if (len(filter(lambda s: s == QtCore.Qt.Checked, states))
                == len(states)):
                state = QtCore.Qt.Checked
            elif (len(filter(lambda s: s == QtCore.Qt.Unchecked, states))
                  == len(states)):
                state = QtCore.Qt.Unchecked
            else:
                state = QtCore.Qt.PartiallyChecked
            parent.setCheckState(0, state)
            parent = parent.parent()

# Public methods:
    def saveState(self):
        '''
        Saves paths to configuration.
        '''
        config.set(self._CONFIG_NAME, self._CONFIG_SECTION_LOCATIONS,
                   "enabled", location.get(enabled=True))
        config.set(self._CONFIG_NAME, self._CONFIG_SECTION_LOCATIONS,
                   "disabled", location.get(enabled=False))

    def loadState(self):
        '''
        Restores paths from configuration.
        ''' 
        enabled = config.getList(self._CONFIG_NAME,
                                 self._CONFIG_SECTION_LOCATIONS,
                                 "enabled", [])
        disabled = config.getList(self._CONFIG_NAME,
                                  self._CONFIG_SECTION_LOCATIONS,
                                  "disabled", [])
        for path in disabled:
            message = self._addLocation(path)
            if message:
                log.warning(message)
        for path in enabled:
            message = self._addLocation(path)
            if message:
                log.warning(message)
            else:
                self._locItems[path].setCheckState(0, QtCore.Qt.Checked)
        self._loaded = True