Beispiel #1
0
class TestConfigToolApp(unittest.TestCase):
    """
    Test suite to verify the functionality of the ConfigToolApp class.

    Tests interact like an end user (using QtTest). Expect the app to be rendered.

    NOTE: most tests will follow this format:
        1. Get current config setting
        2. Make UI change (config change happens immediately)
        3. Reparse config file
        4. Test that has changed (using the previous and new)
    """
    def setUp(self):
        """
        Stardard init method: runs before each test_* method

        Initializes a QtGui.QApplication and ConfigToolApp object.
        ConfigToolApp.show() causes the UI to be rendered.
        """
        self.profile_manager = ProfileManager(tempfile.mkdtemp())
        profile = self.profile_manager.get('testing')
        config = profile.get_config('freeseer.conf',
                                    settings.FreeseerConfig,
                                    storage_args=['Global'],
                                    read_only=False)

        self.app = QtGui.QApplication([])
        self.config_tool = ConfigToolApp(profile, config)
        self.config_tool.show()

    def tearDown(self):
        """
        Standard tear down method. Runs after each test_* method.

        This method closes the ConfigToolApp by clicking the "close" button
        """

        QtTest.QTest.mouseClick(self.config_tool.mainWidget.closePushButton,
                                Qt.Qt.LeftButton)
        shutil.rmtree(self.profile_manager._base_folder)
        del self.config_tool.app
        self.app.deleteLater()

    def test_default_widget(self):
        self.assertEqual(self.config_tool.currentWidget,
                         self.config_tool.generalWidget)

    def check_combobox_corner_cases_frontend(self, combobox_widget):
        """
        Tests that a given QtComboBox has:
        - a default selected item
        - does not blow up on the minimum and maximum index item in the combobox list
        """
        index = combobox_widget.currentIndex()
        combobox_widget.setCurrentIndex(0)
        self.assertEquals(combobox_widget.currentIndex(), 0)
        self.assertIsNot(combobox_widget.currentText(), None)
        combobox_widget.setCurrentIndex(combobox_widget.count() - 1)
        self.assertEquals(combobox_widget.currentIndex(),
                          (combobox_widget.count() - 1))
        self.assertIsNot(combobox_widget.currentText(), None)
        combobox_widget.setCurrentIndex(index)
        self.assertEquals(combobox_widget.currentIndex(), index)
        self.assertIsNot(combobox_widget.currentText(), None)

    def select_general_settings_tab(self):
        # Select "General" tab
        item = self.config_tool.mainWidget.optionsTreeWidget.findItems(
            self.config_tool.generalString, QtCore.Qt.MatchExactly)
        self.assertFalse(not item or item[0] is None)
        self.config_tool.mainWidget.optionsTreeWidget.setCurrentItem(item[0])
        QtTest.QTest.mouseClick(self.config_tool.mainWidget.optionsTreeWidget,
                                Qt.Qt.LeftButton)

    def test_general_settings_checkbox(self):
        """
        Test the config tool's General Tab auto-hide system tray icon checkbox with simulated user input
        """
        self.select_general_settings_tab()
        # Test disabled checkbox
        self.config_tool.currentWidget.autoHideCheckBox.setChecked(False)
        self.assertEqual(
            self.config_tool.currentWidget.autoHideCheckBox.checkState(),
            QtCore.Qt.Unchecked)
        self.assertFalse(self.config_tool.config.auto_hide)

        # Test enabled checkbox
        self.config_tool.currentWidget.autoHideCheckBox.setChecked(True)
        self.assertEqual(
            self.config_tool.currentWidget.autoHideCheckBox.checkState(),
            QtCore.Qt.Checked)
        self.assertTrue(self.config_tool.config.auto_hide)

    def test_general_settings_dropdown_menu(self):
        """
        Test the config tool's General Tab language selection drop down menu with simulated user input
        """
        self.select_general_settings_tab()
        # Test dropdown menu
        language_combo_box = self.config_tool.generalWidget.languageComboBox
        self.check_combobox_corner_cases_frontend(language_combo_box)

        QtTest.QTest.keyClick(
            language_combo_box, QtCore.Qt.Key_PageUp
        )  # Test simulated user interaction with drop down list
        for i in range(language_combo_box.count() - 2):
            last_language = self.config_tool.config.default_language
            QtTest.QTest.keyClick(language_combo_box, QtCore.Qt.Key_Down)
            current_language = self.config_tool.config.default_language
            self.assertNotEqual(last_language, current_language)

        # Test frontend constants
        self.assertNotEqual(
            language_combo_box.findText('Deutsch'),
            -1)  # Assert there are multiple languages in the menu
        self.assertNotEqual(language_combo_box.findText('English'), -1)
        self.assertNotEqual(language_combo_box.findText('Nederlands'), -1)

    def test_general_settings_help_reset(self):
        """
        Test the config tool's General Tab help link and reset button with simulated user input
        """
        self.select_general_settings_tab()
        # Test that Help us translate tries to open a web url.
        QtGui.QDesktopServices.openUrl = MagicMock(return_value=None)
        self.config_tool.open_translate_url()
        QtGui.QDesktopServices.openUrl.assert_called_with(
            QtCore.QUrl(
                "http://freeseer.readthedocs.org/en/latest/contribute/translation.html"
            ))

        # Reset
        # The reset test should set the backend config_tool values, simulate a user clicking through the reset popup and
        # verify that the backend config_tool values have been set to defaults.
        # TODO: FIXME. Related to gh#631. The buttons on the dialog cause segfaults in the test environment and prevent
        # the test from being implemented at the present time.
        # self.config_tool.confirm_reset()

    def select_recording_tab(self):
        """
        Helper function used to open up the recording tab for recording tab related tests
        """
        item = self.config_tool.mainWidget.optionsTreeWidget.findItems(
            self.config_tool.avString, QtCore.Qt.MatchExactly)
        self.assertFalse(not item or item[0] is None)
        self.config_tool.mainWidget.optionsTreeWidget.setCurrentItem(item[0])
        QtTest.QTest.mouseClick(self.config_tool.mainWidget.optionsTreeWidget,
                                Qt.Qt.LeftButton)
        self.assertEqual(self.config_tool.currentWidget,
                         self.config_tool.avWidget)

    def test_recording_settings_file(self):
        """
        Simulates a user interacting with the config tool record to file settings.
        """
        self.select_recording_tab()
        # Test disabled checkbox
        self.config_tool.currentWidget.fileGroupBox.setChecked(False)
        self.assertFalse(self.config_tool.config.record_to_file)

        # Test enabled checkbox
        self.config_tool.currentWidget.fileGroupBox.setChecked(True)
        self.assertTrue(self.config_tool.config.record_to_file)
        self.assertIn(self.config_tool.config.record_to_file_plugin,
                      ['Ogg Output', 'WebM Output', 'Raw Output'])

        # Test combo box
        file_combo_box = self.config_tool.avWidget.fileComboBox
        self.check_combobox_corner_cases_frontend(file_combo_box)
        QtTest.QTest.keyClick(
            file_combo_box, QtCore.Qt.Key_PageUp
        )  # Simulate user input to test backend and frontend
        for i in range(file_combo_box.count() - 2):
            last_plugin = self.config_tool.config.record_to_file_plugin
            QtTest.QTest.keyClick(file_combo_box, QtCore.Qt.Key_Down)
            current_plugin = self.config_tool.config.record_to_file_plugin
            self.assertNotEqual(last_plugin, current_plugin)

        # Test frontend text values
        self.assertNotEqual(file_combo_box.findText('Ogg Output'), -1)
        self.assertNotEqual(file_combo_box.findText('WebM Output'), -1)
        self.assertNotEqual(file_combo_box.findText('Raw Output'), -1)

    def test_recording_settings_stream(self):
        """
        Simulates a user interacting with the config tool record to output stream settings.
        """
        self.select_recording_tab()
        # Test disabled checkbox
        self.config_tool.currentWidget.streamGroupBox.setChecked(False)
        self.assertFalse(self.config_tool.config.record_to_stream)

        # Test enabled checkbox
        self.config_tool.currentWidget.streamGroupBox.setChecked(True)
        self.assertTrue(self.config_tool.config.record_to_stream)

        # Test combo box
        stream_combo_box = self.config_tool.avWidget.streamComboBox
        self.check_combobox_corner_cases_frontend(stream_combo_box)
        QtTest.QTest.keyClick(
            stream_combo_box, QtCore.Qt.Key_PageUp
        )  # Simulate user input to test backend and frontend
        for i in range(stream_combo_box.count() - 2):
            last_plugin = self.config_tool.plugman.get_plugin_by_name(
                stream_combo_box.currentText(), 'Output')
            QtTest.QTest.keyClick(stream_combo_box, QtCore.Qt.Key_Down)
            current_plugin = self.config_tool.plugman.get_plugin_by_name(
                stream_combo_box.currentText(), 'Output')
            self.assertNotEqual(last_plugin, current_plugin)

        # Test frontend text values
        self.assertNotEqual(stream_combo_box.findText('RTMP Streaming'), -1)
        self.assertNotEqual(stream_combo_box.findText('Ogg Icecast'), -1)

    def test_recording_settings_video_input(self):
        """
        Simulates a user interacting with the config tool record to video input setting.
        """

        self.select_recording_tab()
        # Test disabled checkbox
        self.config_tool.currentWidget.videoGroupBox.setChecked(False)
        self.assertFalse(self.config_tool.config.enable_video_recording)

        # Test enabled checkbox
        self.config_tool.currentWidget.videoGroupBox.setChecked(True)
        self.assertTrue(self.config_tool.config.enable_video_recording)
        self.assertIn(self.config_tool.config.videomixer,
                      ['Video Passthrough', 'Picture-In-Picture'])

        # Test combo box
        video_mixer_combo_box = self.config_tool.avWidget.videoMixerComboBox
        self.check_combobox_corner_cases_frontend(video_mixer_combo_box)
        QtTest.QTest.keyClick(
            video_mixer_combo_box,
            QtCore.Qt.Key_PageUp)  # Simulate user to test backend/frontend
        for i in range(video_mixer_combo_box.count() - 2):
            last_plugin = self.config_tool.videomixer
            QtTest.QTest.keyClick(video_mixer_combo_box, QtCore.Qt.Key_Down)
            current_plugin = self.config_tool.videomixer
            self.assertNotEqual(last_plugin, current_plugin)

        # Test frontend text values
        self.assertTrue(
            video_mixer_combo_box.findText('Video Passthrough') != -1)
        self.assertTrue(
            video_mixer_combo_box.findText('Picture-In-Picture') != -1)

    def test_recording_settings_audio_input(self):
        """
        Simulates a user interacting with the config tool record to audio input settings.
        """
        self.select_recording_tab()
        # Test disabled checkbox
        self.config_tool.currentWidget.audioGroupBox.setChecked(False)
        self.assertFalse(self.config_tool.config.enable_audio_recording)

        # Test enabled checkbox
        self.config_tool.currentWidget.audioGroupBox.setChecked(True)
        self.assertTrue(self.config_tool.config.enable_audio_recording)
        self.assertIn(self.config_tool.config.audiomixer,
                      ['Audio Passthrough', 'Multiple Audio Inputs'])

        # Test combo box
        audio_mixer_combo_box = self.config_tool.avWidget.audioMixerComboBox
        self.check_combobox_corner_cases_frontend(audio_mixer_combo_box)
        QtTest.QTest.keyClick(
            audio_mixer_combo_box,
            QtCore.Qt.Key_PageUp)  # Simulate user to test backend/frontend
        for i in range(audio_mixer_combo_box.count() - 2):
            last_plugin = self.config_tool.audiomixer
            QtTest.QTest.keyClick(audio_mixer_combo_box, QtCore.Qt.Key_Down)
            current_plugin = self.config_tool.audiomixer
            self.assertNotEqual(last_plugin, current_plugin)

        # Test frontend text values
        self.assertNotEqual(
            audio_mixer_combo_box.findText('Audio Passthrough'), -1)
        self.assertNotEqual(
            audio_mixer_combo_box.findText('Multiple Audio Inputs'), -1)

    def test_plugin_settings(self):
        """
        Simulate a user going through the list of plugins in the plugin settings page of the config tool.

        This test builds a dictionary value based on a traversal of the QTreeWidget that contains the plugins displayed
        in the GUI. The dictionary is then used to assert that plugins exist in the appropriate categories. This test
        also uses a map to relate the GUI's category names to the backend's category names since the two differ.
        """
        item = self.config_tool.mainWidget.optionsTreeWidget.findItems(
            self.config_tool.pluginsString, QtCore.Qt.MatchExactly)
        self.assertFalse(not item or item[0] is None)
        self.config_tool.mainWidget.optionsTreeWidget.setCurrentItem(item[0])
        QtTest.QTest.mouseClick(self.config_tool.mainWidget.optionsTreeWidget,
                                Qt.Qt.LeftButton)
        self.assertEqual(self.config_tool.currentWidget,
                         self.config_tool.pluginWidget)

        # GUI names categories are different than the backend. Define a translation from GUI -> backend
        gui_category_to_backend_category = {
            'Audio Input': 'AudioInput',
            'Audio Mixer': 'AudioMixer',
            'Video Input': 'VideoInput',
            'Video Mixer': 'VideoMixer',
            'Output': 'Output',
            'Input': 'Importer'
        }
        QtTest.QTest.keyClick(self.config_tool.pluginWidget.list,
                              QtCore.Qt.Key_PageUp)
        root = self.config_tool.pluginWidget.list.invisibleRootItem()
        plugin_category = {}  # A dictionary of plugin -> category
        for category_index in range(root.childCount()):
            category = str(
                self.config_tool.pluginWidget.list.currentItem().text(0))
            QtTest.QTest.keyClick(self.config_tool.pluginWidget.list,
                                  QtCore.Qt.Key_Down)
            for plugin_index in range(root.child(category_index).childCount()):
                plugin_name = str(
                    self.config_tool.pluginWidget.list.currentItem().text(0))
                plugin_category[
                    plugin_name] = gui_category_to_backend_category[category]
                QtTest.QTest.keyClick(self.config_tool.pluginWidget.list,
                                      QtCore.Qt.Key_Down)

        # Assert expected categories exist.
        self.assertIn('AudioInput', plugin_category.values())
        self.assertIn('AudioMixer', plugin_category.values())
        self.assertIn('VideoInput', plugin_category.values())
        self.assertIn('VideoMixer', plugin_category.values())
        self.assertIn('Output', plugin_category.values())
        self.assertIn('Importer', plugin_category.values())

        for category in [
                'AudioInput', 'AudioMixer', 'VideoInput', 'VideoMixer',
                'Output', 'Importer'
        ]:
            for plugin in self.config_tool.get_plugins(category):
                self.assertIn(plugin.plugin_object.name, plugin_category)
                self.assertEqual(plugin_category[plugin.plugin_object.name],
                                 category)
                self.assertEqual(category, plugin.plugin_object.CATEGORY)

    def test_logger_settings(self):
        """
        Tests for config tool's Logger tab

        Needs to be tested differently since the
        Config instance isn't affected by changes in this tab.
        """

        # TODO
        pass

    def test_close_configtool(self):
        """
        Tests for config tool's close button
        """

        self.assertTrue(self.config_tool.mainWidget.isVisible())
        QtTest.QTest.mouseClick(self.config_tool.mainWidget.closePushButton,
                                Qt.Qt.LeftButton)
        self.assertFalse(self.config_tool.mainWidget.isVisible())

    def test_file_menu_quit(self):
        """
        Tests for config tool's File->Quit
        """

        self.assertTrue(self.config_tool.isVisible())

        # File->Quit
        self.config_tool.actionExit.trigger()
        self.assertFalse(self.config_tool.isVisible())

    def test_help_menu_about(self):
        """
        Tests for config tool's Help->About
        """

        self.assertTrue(self.config_tool.isVisible())

        # Help->About
        self.config_tool.actionAbout.trigger()
        self.assertFalse(self.config_tool.hasFocus())
        self.assertTrue(self.config_tool.aboutDialog.isVisible())

        # Click "Close"
        QtTest.QTest.mouseClick(self.config_tool.aboutDialog.closeButton,
                                Qt.Qt.LeftButton)
        self.assertFalse(self.config_tool.aboutDialog.isVisible())
Beispiel #2
0
class TestConfigToolApp(unittest.TestCase):
    '''
    Test suite to verify the functionality of the ConfigToolApp class.

    Tests interact like an end user (using QtTest). Expect the app to be rendered.

    NOTE: most tests will follow this format:
        1. Get current config setting
        2. Make UI change (config change happens immediately)
        3. Reparse config file
        4. Test that has changed (using the previous and new)
    '''

    def setUp(self):
        '''
        Stardard init method: runs before each test_* method

        Initializes a QtGui.QApplication and ConfigToolApp object.
        ConfigToolApp.show() causes the UI to be rendered.
        '''
        self.profile_manager = ProfileManager(tempfile.mkdtemp())
        profile = self.profile_manager.get('testing')
        config = profile.get_config('freeseer.conf', settings.FreeseerConfig, storage_args=['Global'], read_only=False)

        self.app = QtGui.QApplication([])
        self.config_tool = ConfigToolApp(profile, config)
        self.config_tool.show()

    def tearDown(self):
        '''
        Standard tear down method. Runs after each test_* method.

        This method closes the ConfigToolApp by clicking the "close" button
        '''

        QtTest.QTest.mouseClick(self.config_tool.mainWidget.closePushButton, Qt.Qt.LeftButton)
        shutil.rmtree(self.profile_manager._base_folder)
        del self.config_tool.app
        self.app.deleteLater()

    def test_default_widget(self):
        self.assertTrue(self.config_tool.currentWidget == self.config_tool.generalWidget)

    def test_general_settings(self):
        '''
        Tests for the config tool's General Tab
        '''

        # Select "General" tab
        item = self.config_tool.mainWidget.optionsTreeWidget.findItems(self.config_tool.generalString, QtCore.Qt.MatchExactly)
        self.assertFalse(not item or item[0] is None)
        self.config_tool.mainWidget.optionsTreeWidget.setCurrentItem(item[0])
        QtTest.QTest.mouseClick(self.config_tool.mainWidget.optionsTreeWidget, Qt.Qt.LeftButton)

        # Language drop-down
        # TODO

        # Record directory
        # TODO

        # AutoHide Checkbox
        for i in range(2):
            state = self.config_tool.currentWidget.autoHideCheckBox.checkState()
            expected_state = QtCore.Qt.Unchecked
            if state == QtCore.Qt.Unchecked:
                expected_state = QtCore.Qt.Checked
            self.config_tool.currentWidget.autoHideCheckBox.click()
            self.assertEquals(
                self.config_tool.currentWidget.autoHideCheckBox.checkState(), expected_state)

            self.assertEquals(self.config_tool.config.auto_hide, expected_state == QtCore.Qt.Checked)

    def test_recording_settings(self):
        '''
        Tests for config tool's Recording tab
        '''

        # Select "Recording" tab
        item = self.config_tool.mainWidget.optionsTreeWidget.findItems(self.config_tool.avString, QtCore.Qt.MatchExactly)
        self.assertFalse(not item or item[0] is None)
        self.config_tool.mainWidget.optionsTreeWidget.setCurrentItem(item[0])
        QtTest.QTest.mouseClick(self.config_tool.mainWidget.optionsTreeWidget, Qt.Qt.LeftButton)

        # Recording tab
        self.assertTrue(self.config_tool.currentWidget == self.config_tool.avWidget)

        # Audio Input

        # Checkbox
        for i in range(2):
            #self.config_tool.config.readConfig()
            if self.config_tool.currentWidget.audioGroupBox.isChecked():
                self.assertTrue(self.config_tool.config.enable_audio_recording)
                self.assertTrue(self.config_tool.config.audiomixer == "Audio Passthrough" or
                    self.config_tool.config.audiomixer == "Multiple Audio Inputs")
                self.config_tool.currentWidget.audioGroupBox.setChecked(False)
            else:
                self.assertFalse(self.config_tool.config.enable_audio_recording)
                self.config_tool.currentWidget.audioGroupBox.setChecked(True)

        # Dropdown
        # TODO

        # Video Input
        # Checkbox
        for i in range(2):
            #self.config_tool.config.readConfig()
            if self.config_tool.currentWidget.videoGroupBox.isChecked():
                self.assertTrue(self.config_tool.config.enable_video_recording)
                # TODO: Write better test case for this
                self.assertTrue(self.config_tool.config.videomixer == "Video Passthrough" or
                    self.config_tool.config.videomixer == "Picture-In-Picture")
                self.config_tool.currentWidget.videoGroupBox.setChecked(False)
            else:
                self.assertFalse(self.config_tool.config.enable_video_recording)
                self.config_tool.currentWidget.videoGroupBox.setChecked(True)

        # Dropdown
        # TODO

        # Record to File

        # Checkbox
        for i in range(2):
            #self.config_tool.config.readConfig()
            if self.config_tool.currentWidget.fileGroupBox.isChecked():
                self.assertTrue(self.config_tool.config.record_to_file)
                # TODO: Write better test case for this
                self.assertTrue(self.config_tool.config.record_to_file_plugin == "Ogg Output" or
                    self.config_tool.config.record_to_file_plugin == "WebM Output")
                self.config_tool.currentWidget.fileGroupBox.setChecked(False)
            else:
                self.assertFalse(self.config_tool.config.record_to_file)
                self.config_tool.currentWidget.fileGroupBox.setChecked(True)

        # Dropdown
        # TODO

        # Record to Stream

        # Checkbox
        for i in range(2):
            #self.config_tool.config.readConfig()
            if self.config_tool.currentWidget.streamGroupBox.isChecked():
                self.assertTrue(self.config_tool.config.record_to_stream)
                # TODO: Write better test case for this
                #self.assertTrue(self.config_tool.config.record_to_stream_plugin == None)
                self.config_tool.currentWidget.streamGroupBox.setChecked(False)
            else:
                self.assertFalse(self.config_tool.config.record_to_stream)
                self.config_tool.currentWidget.streamGroupBox.setChecked(True)

        # Dropdown
        # TODO

    def test_plugin_audio_input_settings(self):
        '''
        Tests for config tool's Plugins->Audio Input tab
        '''

        # TODO
        pass

    def test_plugin_audio_mixer_settings(self):
        '''
        Tests for config tool's Plugins->Audio Mixer tab
        '''

        # TODO
        pass

    def test_plugin_video_input_settings(self):
        '''
        Tests for config tool's Plugins->Video Input tab
        '''

        # TODO
        pass

    def test_plugin_video_mixer_settings(self):
        '''
        Tests for config tool's Plugins->Video Mixer tab
        '''

        # TODO
        pass

    def test_plugin_output_settings(self):
        '''
        Tests for config tool's Plugins->Output tab
        '''

        # TODO
        pass

    def test_logger_settings(self):
        '''
        Tests for config tool's Logger tab

        Needs to be tested differently since the
        Config instance isn't affected by changes in this tab.
        '''

        # TODO
        pass

    def test_close_configtool(self):
        '''
        Tests for config tool's close button
        '''

        self.assertTrue(self.config_tool.mainWidget.isVisible())
        QtTest.QTest.mouseClick(self.config_tool.mainWidget.closePushButton, Qt.Qt.LeftButton)
        self.assertFalse(self.config_tool.mainWidget.isVisible())

    def test_file_menu_quit(self):
        '''
        Tests for config tool's File->Quit
        '''

        self.assertTrue(self.config_tool.isVisible())

        # File->Quit
        self.config_tool.actionExit.trigger()
        self.assertFalse(self.config_tool.isVisible())

    def test_help_menu_about(self):
        '''
        Tests for config tool's Help->About
        '''

        self.assertTrue(self.config_tool.isVisible())

        # Help->About
        self.config_tool.actionAbout.trigger()
        self.assertFalse(self.config_tool.hasFocus())
        self.assertTrue(self.config_tool.aboutDialog.isVisible())

        # Click "Close"
        QtTest.QTest.mouseClick(self.config_tool.aboutDialog.closeButton, Qt.Qt.LeftButton)
        self.assertFalse(self.config_tool.aboutDialog.isVisible())
class TestConfigToolApp(unittest.TestCase):
    """
    Test suite to verify the functionality of the ConfigToolApp class.

    Tests interact like an end user (using QtTest). Expect the app to be rendered.

    NOTE: most tests will follow this format:
        1. Get current config setting
        2. Make UI change (config change happens immediately)
        3. Reparse config file
        4. Test that has changed (using the previous and new)
    """

    def setUp(self):
        """
        Stardard init method: runs before each test_* method

        Initializes a QtGui.QApplication and ConfigToolApp object.
        ConfigToolApp.show() causes the UI to be rendered.
        """
        self.profile_manager = ProfileManager(tempfile.mkdtemp())
        profile = self.profile_manager.get('testing')
        config = profile.get_config('freeseer.conf', settings.FreeseerConfig, storage_args=['Global'], read_only=False)

        self.app = QtGui.QApplication([])
        self.config_tool = ConfigToolApp(profile, config)
        self.config_tool.show()

    def tearDown(self):
        """
        Standard tear down method. Runs after each test_* method.

        This method closes the ConfigToolApp by clicking the "close" button
        """

        QtTest.QTest.mouseClick(self.config_tool.mainWidget.closePushButton, Qt.Qt.LeftButton)
        shutil.rmtree(self.profile_manager._base_folder)
        del self.config_tool.app
        self.app.deleteLater()

    def test_default_widget(self):
        self.assertEqual(self.config_tool.currentWidget, self.config_tool.generalWidget)

    def check_combobox_corner_cases_frontend(self, combobox_widget):
        """
        Tests that a given QtComboBox has:
        - a default selected item
        - does not blow up on the minimum and maximum index item in the combobox list
        """
        index = combobox_widget.currentIndex()
        combobox_widget.setCurrentIndex(0)
        self.assertEquals(combobox_widget.currentIndex(), 0)
        self.assertIsNot(combobox_widget.currentText(), None)
        combobox_widget.setCurrentIndex(combobox_widget.count() - 1)
        self.assertEquals(combobox_widget.currentIndex(), (combobox_widget.count() - 1))
        self.assertIsNot(combobox_widget.currentText(), None)
        combobox_widget.setCurrentIndex(index)
        self.assertEquals(combobox_widget.currentIndex(), index)
        self.assertIsNot(combobox_widget.currentText(), None)

    def select_general_settings_tab(self):
        # Select "General" tab
        item = self.config_tool.mainWidget.optionsTreeWidget.findItems(self.config_tool.generalString,
                                                                       QtCore.Qt.MatchExactly)
        self.assertFalse(not item or item[0] is None)
        self.config_tool.mainWidget.optionsTreeWidget.setCurrentItem(item[0])
        QtTest.QTest.mouseClick(self.config_tool.mainWidget.optionsTreeWidget, Qt.Qt.LeftButton)

    def test_general_settings_checkbox(self):
        """
        Test the config tool's General Tab auto-hide system tray icon checkbox with simulated user input
        """
        self.select_general_settings_tab()
        # Test disabled checkbox
        self.config_tool.currentWidget.autoHideCheckBox.setChecked(False)
        self.assertEqual(self.config_tool.currentWidget.autoHideCheckBox.checkState(), QtCore.Qt.Unchecked)
        self.assertFalse(self.config_tool.config.auto_hide)

        # Test enabled checkbox
        self.config_tool.currentWidget.autoHideCheckBox.setChecked(True)
        self.assertEqual(self.config_tool.currentWidget.autoHideCheckBox.checkState(), QtCore.Qt.Checked)
        self.assertTrue(self.config_tool.config.auto_hide)

    def test_general_settings_dropdown_menu(self):
        """
        Test the config tool's General Tab language selection drop down menu with simulated user input
        """
        self.select_general_settings_tab()
        # Test dropdown menu
        language_combo_box = self.config_tool.generalWidget.languageComboBox
        self.check_combobox_corner_cases_frontend(language_combo_box)

        QtTest.QTest.keyClick(language_combo_box, QtCore.Qt.Key_PageUp)  # Test simulated user interaction with drop down list
        for i in range(language_combo_box.count() - 2):
            last_language = self.config_tool.config.default_language
            QtTest.QTest.keyClick(language_combo_box, QtCore.Qt.Key_Down)
            current_language = self.config_tool.config.default_language
            self.assertNotEqual(last_language, current_language)

        # Test frontend constants
        self.assertNotEqual(language_combo_box.findText('Deutsch'), -1)  # Assert there are multiple languages in the menu
        self.assertNotEqual(language_combo_box.findText('English'), -1)
        self.assertNotEqual(language_combo_box.findText('Nederlands'), -1)

    def test_general_settings_help_reset(self):
        """
        Test the config tool's General Tab help link and reset button with simulated user input
        """
        self.select_general_settings_tab()
        # Test that Help us translate tries to open a web url.
        QtGui.QDesktopServices.openUrl = MagicMock(return_value=None)
        self.config_tool.open_translate_url()
        QtGui.QDesktopServices.openUrl.assert_called_with(
            QtCore.QUrl("http://freeseer.readthedocs.org/en/latest/contribute/translation.html")
        )

        # Reset
        # The reset test should set the backend config_tool values, simulate a user clicking through the reset popup and
        # verify that the backend config_tool values have been set to defaults.
        # TODO: FIXME. Related to gh#631. The buttons on the dialog cause segfaults in the test environment and prevent
        # the test from being implemented at the present time.
        # self.config_tool.confirm_reset()

    def select_recording_tab(self):
        """
        Helper function used to open up the recording tab for recording tab related tests
        """
        item = self.config_tool.mainWidget.optionsTreeWidget.findItems(self.config_tool.avString,
                                                                       QtCore.Qt.MatchExactly)
        self.assertFalse(not item or item[0] is None)
        self.config_tool.mainWidget.optionsTreeWidget.setCurrentItem(item[0])
        QtTest.QTest.mouseClick(self.config_tool.mainWidget.optionsTreeWidget, Qt.Qt.LeftButton)
        self.assertEqual(self.config_tool.currentWidget, self.config_tool.avWidget)

    def test_recording_settings_file(self):
        """
        Simulates a user interacting with the config tool record to file settings.
        """
        self.select_recording_tab()
        # Test disabled checkbox
        self.config_tool.currentWidget.fileGroupBox.setChecked(False)
        self.assertFalse(self.config_tool.config.record_to_file)

        # Test enabled checkbox
        self.config_tool.currentWidget.fileGroupBox.setChecked(True)
        self.assertTrue(self.config_tool.config.record_to_file)
        self.assertIn(self.config_tool.config.record_to_file_plugin, ['Ogg Output', 'WebM Output', 'Raw Output'])

        # Test combo box
        file_combo_box = self.config_tool.avWidget.fileComboBox
        self.check_combobox_corner_cases_frontend(file_combo_box)
        QtTest.QTest.keyClick(file_combo_box, QtCore.Qt.Key_PageUp)  # Simulate user input to test backend and frontend
        for i in range(file_combo_box.count() - 2):
            last_plugin = self.config_tool.config.record_to_file_plugin
            QtTest.QTest.keyClick(file_combo_box, QtCore.Qt.Key_Down)
            current_plugin = self.config_tool.config.record_to_file_plugin
            self.assertNotEqual(last_plugin, current_plugin)

        # Test frontend text values
        self.assertNotEqual(file_combo_box.findText('Ogg Output'), -1)
        self.assertNotEqual(file_combo_box.findText('WebM Output'), -1)
        self.assertNotEqual(file_combo_box.findText('Raw Output'), -1)

    def test_recording_settings_stream(self):
        """
        Simulates a user interacting with the config tool record to output stream settings.
        """
        self.select_recording_tab()
        # Test disabled checkbox
        self.config_tool.currentWidget.streamGroupBox.setChecked(False)
        self.assertFalse(self.config_tool.config.record_to_stream)

        # Test enabled checkbox
        self.config_tool.currentWidget.streamGroupBox.setChecked(True)
        self.assertTrue(self.config_tool.config.record_to_stream)

        # Test combo box
        stream_combo_box = self.config_tool.avWidget.streamComboBox
        self.check_combobox_corner_cases_frontend(stream_combo_box)
        QtTest.QTest.keyClick(stream_combo_box, QtCore.Qt.Key_PageUp)  # Simulate user input to test backend and frontend
        for i in range(stream_combo_box.count() - 2):
            last_plugin = self.config_tool.plugman.get_plugin_by_name(stream_combo_box.currentText(), 'Output')
            QtTest.QTest.keyClick(stream_combo_box, QtCore.Qt.Key_Down)
            current_plugin = self.config_tool.plugman.get_plugin_by_name(stream_combo_box.currentText(), 'Output')
            self.assertNotEqual(last_plugin, current_plugin)

        # Test frontend text values
        self.assertNotEqual(stream_combo_box.findText('RTMP Streaming'), -1)
        self.assertNotEqual(stream_combo_box.findText('Ogg Icecast'), -1)

    def test_recording_settings_video_input(self):
        """
        Simulates a user interacting with the config tool record to video input setting.
        """

        self.select_recording_tab()
        # Test disabled checkbox
        self.config_tool.currentWidget.videoGroupBox.setChecked(False)
        self.assertFalse(self.config_tool.config.enable_video_recording)

        # Test enabled checkbox
        self.config_tool.currentWidget.videoGroupBox.setChecked(True)
        self.assertTrue(self.config_tool.config.enable_video_recording)
        self.assertIn(self.config_tool.config.videomixer, ['Video Passthrough', 'Picture-In-Picture'])

        # Test combo box
        video_mixer_combo_box = self.config_tool.avWidget.videoMixerComboBox
        self.check_combobox_corner_cases_frontend(video_mixer_combo_box)
        QtTest.QTest.keyClick(video_mixer_combo_box, QtCore.Qt.Key_PageUp)  # Simulate user to test backend/frontend
        for i in range(video_mixer_combo_box.count() - 2):
            last_plugin = self.config_tool.videomixer
            QtTest.QTest.keyClick(video_mixer_combo_box, QtCore.Qt.Key_Down)
            current_plugin = self.config_tool.videomixer
            self.assertNotEqual(last_plugin, current_plugin)

        # Test frontend text values
        self.assertTrue(video_mixer_combo_box.findText('Video Passthrough') != -1)
        self.assertTrue(video_mixer_combo_box.findText('Picture-In-Picture') != -1)

    def test_recording_settings_audio_input(self):
        """
        Simulates a user interacting with the config tool record to audio input settings.
        """
        self.select_recording_tab()
        # Test disabled checkbox
        self.config_tool.currentWidget.audioGroupBox.setChecked(False)
        self.assertFalse(self.config_tool.config.enable_audio_recording)

        # Test enabled checkbox
        self.config_tool.currentWidget.audioGroupBox.setChecked(True)
        self.assertTrue(self.config_tool.config.enable_audio_recording)
        self.assertIn(self.config_tool.config.audiomixer, ['Audio Passthrough', 'Multiple Audio Inputs'])

        # Test combo box
        audio_mixer_combo_box = self.config_tool.avWidget.audioMixerComboBox
        self.check_combobox_corner_cases_frontend(audio_mixer_combo_box)
        QtTest.QTest.keyClick(audio_mixer_combo_box, QtCore.Qt.Key_PageUp)  # Simulate user to test backend/frontend
        for i in range(audio_mixer_combo_box.count() - 2):
            last_plugin = self.config_tool.audiomixer
            QtTest.QTest.keyClick(audio_mixer_combo_box, QtCore.Qt.Key_Down)
            current_plugin = self.config_tool.audiomixer
            self.assertNotEqual(last_plugin, current_plugin)

        # Test frontend text values
        self.assertNotEqual(audio_mixer_combo_box.findText('Audio Passthrough'), -1)
        self.assertNotEqual(audio_mixer_combo_box.findText('Multiple Audio Inputs'), -1)

    def test_plugin_settings(self):
        """
        Simulate a user going through the list of plugins in the plugin settings page of the config tool.

        This test builds a dictionary value based on a traversal of the QTreeWidget that contains the plugins displayed
        in the GUI. The dictionary is then used to assert that plugins exist in the appropriate categories. This test
        also uses a map to relate the GUI's category names to the backend's category names since the two differ.
        """
        item = self.config_tool.mainWidget.optionsTreeWidget.findItems(self.config_tool.pluginsString,
                                                                       QtCore.Qt.MatchExactly)
        self.assertFalse(not item or item[0] is None)
        self.config_tool.mainWidget.optionsTreeWidget.setCurrentItem(item[0])
        QtTest.QTest.mouseClick(self.config_tool.mainWidget.optionsTreeWidget, Qt.Qt.LeftButton)
        self.assertEqual(self.config_tool.currentWidget, self.config_tool.pluginWidget)

        # GUI names categories are different than the backend. Define a translation from GUI -> backend
        gui_category_to_backend_category = {
            'Audio Input': 'AudioInput',
            'Audio Mixer': 'AudioMixer',
            'Video Input': 'VideoInput',
            'Video Mixer': 'VideoMixer',
            'Output': 'Output',
            'Input': 'Importer'
        }
        QtTest.QTest.keyClick(self.config_tool.pluginWidget.list, QtCore.Qt.Key_PageUp)
        root = self.config_tool.pluginWidget.list.invisibleRootItem()
        plugin_category = {}  # A dictionary of plugin -> category
        for category_index in range(root.childCount()):
            category = str(self.config_tool.pluginWidget.list.currentItem().text(0))
            QtTest.QTest.keyClick(self.config_tool.pluginWidget.list, QtCore.Qt.Key_Down)
            for plugin_index in range(root.child(category_index).childCount()):
                plugin_name = str(self.config_tool.pluginWidget.list.currentItem().text(0))
                plugin_category[plugin_name] = gui_category_to_backend_category[category]
                QtTest.QTest.keyClick(self.config_tool.pluginWidget.list, QtCore.Qt.Key_Down)

        # Assert expected categories exist.
        self.assertIn('AudioInput', plugin_category.values())
        self.assertIn('AudioMixer', plugin_category.values())
        self.assertIn('VideoInput', plugin_category.values())
        self.assertIn('VideoMixer', plugin_category.values())
        self.assertIn('Output', plugin_category.values())
        self.assertIn('Importer', plugin_category.values())

        for category in ['AudioInput', 'AudioMixer', 'VideoInput', 'VideoMixer', 'Output', 'Importer']:
            for plugin in self.config_tool.get_plugins(category):
                self.assertIn(plugin.plugin_object.name, plugin_category)
                self.assertEqual(plugin_category[plugin.plugin_object.name], category)
                self.assertEqual(category, plugin.plugin_object.CATEGORY)

    def test_logger_settings(self):
        """
        Tests for config tool's Logger tab

        Needs to be tested differently since the
        Config instance isn't affected by changes in this tab.
        """

        # TODO
        pass

    def test_close_configtool(self):
        """
        Tests for config tool's close button
        """

        self.assertTrue(self.config_tool.mainWidget.isVisible())
        QtTest.QTest.mouseClick(self.config_tool.mainWidget.closePushButton, Qt.Qt.LeftButton)
        self.assertFalse(self.config_tool.mainWidget.isVisible())

    def test_file_menu_quit(self):
        """
        Tests for config tool's File->Quit
        """

        self.assertTrue(self.config_tool.isVisible())

        # File->Quit
        self.config_tool.actionExit.trigger()
        self.assertFalse(self.config_tool.isVisible())

    def test_help_menu_about(self):
        """
        Tests for config tool's Help->About
        """

        self.assertTrue(self.config_tool.isVisible())

        # Help->About
        self.config_tool.actionAbout.trigger()
        self.assertFalse(self.config_tool.hasFocus())
        self.assertTrue(self.config_tool.aboutDialog.isVisible())

        # Click "Close"
        QtTest.QTest.mouseClick(self.config_tool.aboutDialog.closeButton, Qt.Qt.LeftButton)
        self.assertFalse(self.config_tool.aboutDialog.isVisible())