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'
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'
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) == ''
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
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
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
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
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
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
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
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>'
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'])
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')
def default_config(): return Config(framework=None, wdir=os.getcwd())
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()