def test_unittestwidget_set_config_does_not_emit_when_invalid(qtbot):
    widget = UnitTestWidget(None)
    qtbot.addWidget(widget)
    config = Config(wdir=os.getcwd(), framework=None)
    with qtbot.assertNotEmitted(widget.sig_newconfig):
        widget.config = config
    assert widget.config == config
def test_run_tests_and_display_results(qtbot, tmpdir, monkeypatch, framework):
    """Basic check."""
    os.chdir(tmpdir.strpath)
    testfilename = tmpdir.join('test_foo.py').strpath

    with open(testfilename, 'w') as f:
        f.write("def test_ok(): assert 1+1 == 2\n"
                "def test_fail(): assert 1+1 == 3\n")

    MockQMessageBox = Mock()
    monkeypatch.setattr('spyder_unittest.widgets.unittestgui.QMessageBox',
                        MockQMessageBox)

    widget = UnitTestWidget(None)
    qtbot.addWidget(widget)
    config = Config(wdir=tmpdir.strpath, framework=framework)
    with qtbot.waitSignal(widget.sig_finished, timeout=10000, raising=True):
        widget.run_tests(config)

    MockQMessageBox.assert_not_called()
    dt = widget.datatree
    itemcount = dt.topLevelItemCount()
    assert itemcount == 2
    assert dt.topLevelItem(0).data(0, Qt.DisplayRole) == 'ok'
    assert dt.topLevelItem(0).data(1, Qt.DisplayRole) == 'test_ok'
    assert dt.topLevelItem(0).data(1, Qt.ToolTipRole) == 'test_foo.test_ok'
    assert dt.topLevelItem(0).data(2, Qt.DisplayRole) == ''
    assert dt.topLevelItem(1).data(0, Qt.DisplayRole) == 'failure'
    assert dt.topLevelItem(1).data(1, Qt.DisplayRole) == 'test_fail'
    assert dt.topLevelItem(1).data(1, Qt.ToolTipRole) == 'test_foo.test_fail'
Exemple #3
0
def test_plugin_config(plugin, tmpdir, qtbot):
    # Test config file does not exist and config is empty
    config_file_path = tmpdir.join('.spyproject', 'config', 'unittest.ini')
    assert not config_file_path.check()
    assert plugin.unittestwidget.config is None

    # Open project
    project = EmptyProject(str(tmpdir))
    plugin.main.projects.get_active_project = lambda: project
    plugin.main.projects.get_active_project_path = lambda: project.root_path
    plugin.handle_project_change()

    # Test config file does exist but config is empty
    assert config_file_path.check()
    assert 'framework = ' in config_file_path.read().splitlines()
    assert plugin.unittestwidget.config is None

    # Set config and test that this is recorded in config file
    config = Config(framework='unittest', wdir=str(tmpdir))
    with qtbot.waitSignal(plugin.unittestwidget.sig_newconfig):
        plugin.unittestwidget.config = config
    assert 'framework = unittest' in config_file_path.read().splitlines()

    # Close project and test that config is empty
    plugin.main.projects.get_active_project = lambda: None
    plugin.main.projects.get_active_project_path = lambda: None
    plugin.handle_project_change()
    assert plugin.unittestwidget.config is None

    # Re-open project and test that config is correctly read
    plugin.main.projects.get_active_project = lambda: project
    plugin.main.projects.get_active_project_path = lambda: project.root_path
    plugin.handle_project_change()
    assert plugin.unittestwidget.config == config
def test_runnerbase_prepare_process(monkeypatch, pythonpath, env_pythonpath):
    MockQProcess = Mock()
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.QProcess',
                        MockQProcess)
    mock_process = MockQProcess()

    MockEnvironment = Mock()
    monkeypatch.setattr(
        'spyder_unittest.backend.runnerbase.QProcessEnvironment.systemEnvironment',
        MockEnvironment)
    mock_environment = MockEnvironment()
    mock_environment.configure_mock(**{'value.return_value': env_pythonpath})

    config = Config('myRunner', 'wdir')
    runner = RunnerBase(None, 'results')
    runner._prepare_process(config, pythonpath)

    mock_process.setWorkingDirectory.assert_called_once_with('wdir')
    mock_process.finished.connect.assert_called_once_with(runner.finished)
    if pythonpath:
        if env_pythonpath:
            mock_environment.insert.assert_any_call('PYTHONPATH',
                                                    'pythonpath{}{}'.format(
                                                        os.pathsep,
                                                        env_pythonpath))
        else:
            mock_environment.insert.assert_any_call('PYTHONPATH', 'pythonpath')
        mock_process.setProcessEnvironment.assert_called_once()
    else:
        mock_environment.insert.assert_not_called()
        mock_process.setProcessEnvironment.assert_not_called()
def test_unittestwidget_config_with_unknown_framework_invalid(qtbot):
    """Check that if the framework in the config is not known,
    config_is_valid() returns False"""
    widget = UnitTestWidget(None)
    qtbot.addWidget(widget)
    config = Config(wdir=os.getcwd(), framework='unknown framework')
    assert widget.config_is_valid(config) == False
def test_run_tests_and_display_results(qtbot, tmpdir, monkeypatch, framework):
    """Basic integration test."""
    os.chdir(tmpdir.strpath)
    testfilename = tmpdir.join('test_foo.py').strpath

    with open(testfilename, 'w') as f:
        f.write("def test_ok(): assert 1+1 == 2\n"
                "def test_fail(): assert 1+1 == 3\n")

    MockQMessageBox = Mock()
    monkeypatch.setattr('spyder_unittest.widgets.unittestgui.QMessageBox',
                        MockQMessageBox)

    widget = UnitTestWidget(None)
    qtbot.addWidget(widget)
    config = Config(wdir=tmpdir.strpath, framework=framework)
    with qtbot.waitSignal(widget.sig_finished, timeout=10000, raising=True):
        widget.run_tests(config)

    MockQMessageBox.assert_not_called()
    model = widget.testdatamodel
    assert model.rowCount() == 2
    assert model.index(0, 0).data(
        Qt.DisplayRole) == 'ok' if framework == 'nose' else 'passed'
    assert model.index(0, 1).data(Qt.DisplayRole) == 't.test_ok'
    assert model.index(0, 1).data(Qt.ToolTipRole) == 'test_foo.test_ok'
    assert model.index(0, 2).data(Qt.DisplayRole) == ''
    assert model.index(1, 0).data(
        Qt.DisplayRole) == 'failure' if framework == 'nose' else 'failed'
    assert model.index(1, 1).data(Qt.DisplayRole) == 't.test_fail'
    assert model.index(1, 1).data(Qt.ToolTipRole) == 'test_foo.test_fail'
Exemple #7
0
def test_pytestrunner_start(monkeypatch):
    MockQProcess = Mock()
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.QProcess',
                        MockQProcess)
    mock_process = MockQProcess()
    mock_process.systemEnvironment = lambda: ['VAR=VALUE', 'PYTHONPATH=old']

    MockEnvironment = Mock()
    monkeypatch.setattr(
        'spyder_unittest.backend.runnerbase.QProcessEnvironment',
        MockEnvironment)
    mock_environment = MockEnvironment()

    mock_remove = Mock(side_effect=OSError())
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.os.remove',
                        mock_remove)

    runner = PyTestRunner(None, 'results')
    config = Config('py.test', 'wdir')
    runner.start(config, ['pythondir'])

    mock_process.setWorkingDirectory.assert_called_once_with('wdir')
    mock_process.finished.connect.assert_called_once_with(runner.finished)
    mock_process.setProcessEnvironment.assert_called_once_with(
        mock_environment)
    mock_process.start.assert_called_once_with(
        get_python_executable(), ['-m', 'pytest', '--junit-xml', 'results'])

    mock_environment.insert.assert_any_call('VAR', 'VALUE')
    # mock_environment.insert.assert_any_call('PYTHONPATH', 'pythondir:old')
    # TODO: Find out why above test fails
    mock_remove.called_once_with('results')
def test_run_tests_using_unittest_and_display_results(qtbot, tmpdir,
                                                      monkeypatch):
    """Basic check."""
    os.chdir(tmpdir.strpath)
    testfilename = tmpdir.join('test_foo.py').strpath

    with open(testfilename, 'w') as f:
        f.write("import unittest\n"
                "class MyTest(unittest.TestCase):\n"
                "   def test_ok(self): self.assertEqual(1+1, 2)\n"
                "   def test_fail(self): self.assertEqual(1+1, 3)\n")

    MockQMessageBox = Mock()
    monkeypatch.setattr('spyder_unittest.widgets.unittestgui.QMessageBox',
                        MockQMessageBox)

    widget = UnitTestWidget(None)
    qtbot.addWidget(widget)
    config = Config(wdir=tmpdir.strpath, framework='unittest')
    with qtbot.waitSignal(widget.sig_finished, timeout=10000, raising=True):
        widget.run_tests(config)

    MockQMessageBox.assert_not_called()
    model = widget.testdatamodel
    assert model.rowCount() == 2
    assert model.index(0, 0).data(Qt.DisplayRole) == 'FAIL'
    assert model.index(0, 1).data(Qt.DisplayRole) == 't.M.test_fail'
    assert model.index(0,
                       1).data(Qt.ToolTipRole) == 'test_foo.MyTest.test_fail'
    assert model.index(0, 2).data(Qt.DisplayRole) == ''
    assert model.index(1, 0).data(Qt.DisplayRole) == 'ok'
    assert model.index(1, 1).data(Qt.DisplayRole) == 't.M.test_ok'
    assert model.index(1, 1).data(Qt.ToolTipRole) == 'test_foo.MyTest.test_ok'
    assert model.index(1, 2).data(Qt.DisplayRole) == ''
Exemple #9
0
    def load_config(self):
        """
        Load test configuration from project preferences.

        If the test configuration stored in the project preferences is valid,
        then use it. If it is not valid (e.g., because the user never
        configured testing for this project) or no project is opened, then
        invalidate the current test configuration.
        """
        project = self.main.projects.get_active_project()
        if not project:
            self.unittestwidget.set_config_without_emit(None)
            return

        try:
            project_conf = project.CONF[self.CONF_SECTION]
        except KeyError:
            project_conf = ProjectConfig(name=self.CONF_SECTION,
                                         root_path=project.root_path,
                                         filename=self.CONF_SECTION + '.ini',
                                         defaults=self.CONF_DEFAULTS,
                                         load=True,
                                         version=self.CONF_VERSION)
            project.CONF[self.CONF_SECTION] = project_conf

        new_config = Config(framework=project_conf.get(self.CONF_SECTION,
                                                       'framework'),
                            wdir=project_conf.get(self.CONF_SECTION, 'wdir'))
        if not self.unittestwidget.config_is_valid(new_config):
            new_config = None
        self.unittestwidget.set_config_without_emit(new_config)
def test_unittestwidget_set_config_emits_newconfig(qtbot):
    widget = UnitTestWidget(None)
    qtbot.addWidget(widget)
    config = Config(wdir=os.getcwd(), framework='unittest')
    with qtbot.waitSignal(widget.sig_newconfig) as blocker:
        widget.config = config
    assert blocker.args == [config]
    assert widget.config == config
def test_run_tests_with_pre_test_hook_returning_false(qtbot):
    widget = UnitTestWidget(None)
    mockRunner = Mock()
    widget.framework_registry.create_runner = Mock(return_value=mockRunner)
    widget.pre_test_hook = Mock(return_value=False)
    widget.run_tests(Config())
    assert widget.pre_test_hook.call_count == 1
    assert mockRunner.start.call_count == 0
Exemple #12
0
def test_logreport_to_testresult_passed():
    report = standard_logreport_output()
    expected = TestResult(Category.OK,
                          'ok',
                          'foo.bar',
                          time=42,
                          filename=osp.join('ham', 'foo.py'),
                          lineno=24)
    assert logreport_to_testresult(report, Config(wdir='ham')) == expected
def test_run_tests_starts_testrunner(qtbot):
    widget = UnitTestWidget(None)
    mockRunner = Mock()
    widget.framework_registry.create_runner = Mock(return_value=mockRunner)
    config = Config(wdir=None, framework='ham')
    widget.run_tests(config)
    assert widget.framework_registry.create_runner.call_count == 1
    assert widget.framework_registry.create_runner.call_args[0][0] == 'ham'
    assert mockRunner.start.call_count == 1
Exemple #14
0
 def configure(self):
     """Configure tests."""
     if self.config:
         oldconfig = self.config
     else:
         oldconfig = Config(wdir=self.default_wdir)
     config = ask_for_config(oldconfig)
     if config:
         self.config = config
Exemple #15
0
 def configure(self):
     """Configure tests."""
     if self.config:
         oldconfig = self.config
     else:
         oldconfig = Config(wdir=self.default_wdir)
     frameworks = self.framework_registry.frameworks
     config = ask_for_config(frameworks, oldconfig)
     if config:
         self.config = config
Exemple #16
0
def test_logreport_to_testresult_skipped():
    report = standard_logreport_output()
    report['when'] = 'setup'
    report['outcome'] = 'skipped'
    report['longrepr'] = ('file', 24, 'skipmsg')
    expected = TestResult(Category.SKIP,
                          'skipped',
                          'foo.bar',
                          time=42,
                          extra_text='skipmsg',
                          filename=osp.join('ham', 'foo.py'),
                          lineno=24)
    assert logreport_to_testresult(report, Config(wdir='ham')) == expected
Exemple #17
0
def test_logreport_to_testresult_failed():
    report = standard_logreport_output()
    report['outcome'] = 'failed'
    report['message'] = 'msg'
    report['longrepr'] = 'exception text'
    expected = TestResult(Category.FAIL,
                          'failure',
                          'foo.bar',
                          message='msg',
                          time=42,
                          extra_text='exception text',
                          filename=osp.join('ham', 'foo.py'),
                          lineno=24)
    assert logreport_to_testresult(report, Config(wdir='ham')) == expected
Exemple #18
0
def test_logreport_to_testresult_with_output():
    report = standard_logreport_output()
    report['sections'] = [['Captured stdout call', 'ham\n'],
                          ['Captured stderr call', 'spam\n']]
    txt = ('----- Captured stdout call -----\nham\n'
           '----- Captured stderr call -----\nspam\n')
    expected = TestResult(Category.OK,
                          'ok',
                          'foo.bar',
                          time=42,
                          extra_text=txt,
                          filename=osp.join('ham', 'foo.py'),
                          lineno=24)
    assert logreport_to_testresult(report, Config(wdir='ham')) == expected
Exemple #19
0
def test_pytestrunner_process_output_with_logreport_passed(qtbot):
    runner = PyTestRunner(None)
    runner.config = Config(wdir='ham')
    output = [standard_logreport_output()]
    with qtbot.waitSignal(runner.sig_testresult) as blocker:
        runner.process_output(output)
    expected = [
        TestResult(Category.OK,
                   'ok',
                   'foo.bar',
                   time=42,
                   filename=osp.join('ham', 'foo.py'),
                   lineno=24)
    ]
    assert blocker.args == [expected]
def test_run_with_no_tests_discovered_and_display_results(
        qtbot, tmpdir, monkeypatch, framework):
    """Basic integration test."""
    os.chdir(tmpdir.strpath)

    MockQMessageBox = Mock()
    monkeypatch.setattr('spyder_unittest.widgets.unittestgui.QMessageBox',
                        MockQMessageBox)

    widget = UnitTestWidget(None)
    qtbot.addWidget(widget)
    config = Config(wdir=tmpdir.strpath, framework=framework)
    with qtbot.waitSignal(widget.sig_finished, timeout=10000, raising=True):
        widget.run_tests(config)

    MockQMessageBox.assert_not_called()
    model = widget.testdatamodel
    assert model.rowCount() == 0
    assert widget.status_label.text() == '<b>No results to show.</b>'
Exemple #21
0
def test_pytestrunner_start(monkeypatch):
    MockQProcess = Mock()
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.QProcess',
                        MockQProcess)
    mock_process = MockQProcess()
    mock_process.systemEnvironment = lambda: ['VAR=VALUE', 'PYTHONPATH=old']

    MockEnvironment = Mock()
    monkeypatch.setattr(
        'spyder_unittest.backend.runnerbase.QProcessEnvironment',
        MockEnvironment)
    mock_environment = MockEnvironment()

    mock_remove = Mock(side_effect=OSError())
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.os.remove',
                        mock_remove)

    MockZMQStreamReader = Mock()
    monkeypatch.setattr('spyder_unittest.backend.pytestrunner.ZmqStreamReader',
                        MockZMQStreamReader)
    mock_reader = MockZMQStreamReader()
    mock_reader.port = 42

    runner = PyTestRunner(None, 'results')
    config = Config('pytest', 'wdir')
    runner.start(config, ['pythondir'])

    mock_process.setWorkingDirectory.assert_called_once_with('wdir')
    mock_process.finished.connect.assert_called_once_with(runner.finished)
    mock_process.setProcessEnvironment.assert_called_once_with(
        mock_environment)

    workerfile = os.path.abspath(
        os.path.join(os.path.dirname(__file__), os.pardir, 'pytestworker.py'))
    mock_process.start.assert_called_once_with(get_python_executable(),
                                               [workerfile, '42'])

    mock_environment.insert.assert_any_call('VAR', 'VALUE')
    # mock_environment.insert.assert_any_call('PYTHONPATH', 'pythondir:old')
    # TODO: Find out why above test fails
    mock_remove.called_once_with('results')

    assert runner.reader is mock_reader
def test_pytestrunner_start(monkeypatch):
    MockZMQStreamReader = Mock()
    monkeypatch.setattr(
        'spyder_unittest.backend.pytestrunner.ZmqStreamReader',
        MockZMQStreamReader)
    mock_reader = MockZMQStreamReader()

    MockRunnerBase = Mock(name='RunnerBase')
    monkeypatch.setattr('spyder_unittest.backend.pytestrunner.RunnerBase',
                        MockRunnerBase)

    runner = PyTestRunner(None, 'results')
    config = Config()
    runner.start(config, ['pythondir'])
    assert runner.config is config
    assert runner.reader is mock_reader
    runner.reader.sig_received.connect.assert_called_once_with(
        runner.process_output)
    MockRunnerBase.start.assert_called_once_with(runner, config, ['pythondir'])
Exemple #23
0
def test():
    """
    Run widget test.

    Show the unittest widgets, configured so that our own tests are run when
    the user clicks "Run tests".
    """
    from spyder.utils.qthelpers import qapplication
    app = qapplication()
    widget = UnitTestWidget(None)

    # set wdir to .../spyder_unittest
    wdir = osp.abspath(osp.join(osp.dirname(__file__), osp.pardir))
    widget.config = Config('pytest', wdir)

    # add wdir's parent to python path, so that `import spyder_unittest` works
    rootdir = osp.abspath(osp.join(wdir, osp.pardir))
    widget.pythonpath = [rootdir]

    widget.resize(800, 600)
    widget.show()
    sys.exit(app.exec_())
def test_stop_running_tests_before_testresult_is_received(qtbot, tmpdir):
    os.chdir(tmpdir.strpath)
    testfilename = tmpdir.join('test_foo.py').strpath

    with open(testfilename, 'w') as f:
        f.write("import unittest\n"
                "import time\n"
                "class MyTest(unittest.TestCase):\n"
                "   def test_ok(self): \n"
                "      time.sleep(3)\n"
                "      self.assertTrue(True)\n")

    widget = UnitTestWidget(None)
    qtbot.addWidget(widget)
    config = Config(wdir=tmpdir.strpath, framework='unittest')
    widget.run_tests(config)
    qtbot.waitUntil(
        lambda: widget.testrunner.process.state() == QProcess.Running)
    widget.testrunner.stop_if_running()

    assert widget.testdatamodel.rowCount() == 0
    assert widget.status_label.text() == ''
    def load_config(self):
        """
        Load test configuration from project preferences.

        If the test configuration stored in the project preferences is valid,
        then use it. If it is not valid (e.g., because the user never
        configured testing for this project) or no project is opened, then
        invalidate the current test configuration.

        If necessary, patch the project preferences to include this plugin's
        config options.
        """
        project = self.main.projects.get_active_project()
        if not project:
            self.unittestwidget.set_config_without_emit(None)
            return

        if self.CONF_SECTION not in project.config._name_map:
            project.config._name_map = project.config._name_map.copy()
            project.config._name_map.update(self.CONF_NAMEMAP)

        if self.CONF_SECTION not in project.config._configs_map:
            config_class = project.config.get_config_class()
            path = osp.join(project.root_path, '.spyproject', 'config')
            conf = config_class(name=self.CONF_SECTION,
                                defaults=self.CONF_DEFAULTS,
                                path=path,
                                load=True,
                                version=self.CONF_VERSION)
            project.config._configs_map[self.CONF_SECTION] = conf

        new_config = Config(framework=project.get_option(
            self.CONF_SECTION, 'framework'),
                            wdir=project.get_option(self.CONF_SECTION, 'wdir'))
        if not self.unittestwidget.config_is_valid(new_config):
            new_config = None
        self.unittestwidget.set_config_without_emit(new_config)
def test_runnerbase_start(monkeypatch):
    MockQProcess = Mock()
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.QProcess',
                        MockQProcess)
    mock_process = MockQProcess()

    mock_remove = Mock(side_effect=OSError())
    monkeypatch.setattr('spyder_unittest.backend.runnerbase.os.remove',
                        mock_remove)

    monkeypatch.setattr(
        'spyder_unittest.backend.runnerbase.get_python_executable',
        lambda: 'python')

    runner = RunnerBase(None, 'results')
    runner._prepare_process = lambda c, p: mock_process
    runner.create_argument_list = lambda: ['arg1', 'arg2']
    config = Config('pytest', 'wdir')
    mock_process.waitForStarted = lambda: False
    with pytest.raises(RuntimeError):
        runner.start(config, ['pythondir'])

    mock_process.start.assert_called_once_with('python', ['arg1', 'arg2'])
    mock_remove.assert_called_once_with('results')
Exemple #27
0
def default_config():
    return Config(framework=None, wdir=os.getcwd())
Exemple #28
0
def test_configdialog_ok_setting_framework_initially_enables_ok(qtbot):
    config = Config(framework='eggs', wdir=os.getcwd())
    configdialog = ConfigDialog(frameworks, config)
    qtbot.addWidget(configdialog)
    assert configdialog.buttons.button(QDialogButtonBox.Ok).isEnabled()