Subject: [pgadmin4][Patch]: Test cases for the backup module

From: Khushboo Vashi <[email-masked]>
Date: Wed, 25 Apr 2018 14:50:12 +0530

Hi,

Please find the attached patch which covers test cases for the backup
module (RM #3206).

1. Unit test cases
2. End to end regression test cases
3. Feature test cases

Thanks,
Khushboo
diff --git a/web/pgadmin/feature_tests/pg_utilities_backup_test.py b/web/pgadmin/feature_tests/pg_utilities_backup_test.py
new file mode 100644
index 0000000..feca43a
--- /dev/null
+++ b/web/pgadmin/feature_tests/pg_utilities_backup_test.py
@@ -0,0 +1,82 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+import time
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support import expected_conditions as EC
+from regression.feature_utils.base_feature_test import BaseFeatureTest
+from regression.python_test_utils import test_utils
+
+
+class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
+    """ This class test PG utilities - Backup test scenarios """
+
+    scenarios = [
+        ("Test for PG utilities", dict())
+    ]
+
+    def before(self):
+        connection = test_utils.get_db_connection(
+            self.server['db'],
+            self.server['username'],
+            self.server['db_password'],
+            self.server['host'],
+            self.server['port'],
+            self.server['sslmode']
+        )
+        test_utils.drop_database(connection, "acceptance_test_db")
+
+        test_utils.create_database(self.server, "acceptance_test_db")
+        test_utils.create_table(self.server, "acceptance_test_db", "acceptance_test_table")
+        self.page.add_server(self.server)
+
+        self.wait = WebDriverWait(self.page.driver, 10)
+
+    def runTest(self):
+        self.page.toggle_open_server(self.server['name'])
+        self.page.toggle_open_tree_item('Databases')
+        self.page.toggle_open_tree_item('acceptance_test_db')
+        self.driver.find_element_by_link_text("Tools").click()
+
+        self.page.find_by_partial_link_text("Backup...").click()
+
+        time.sleep(0.5)
+
+        self.page.fill_input_by_field_name("file", "test_backup_file")
+        self.page.find_by_xpath("//button[contains(@class,'fa-save') and contains(.,'Backup')]").click()
+
+        self.page.wait_for_element_to_disappear(
+            lambda driver: driver.find_element_by_css_selector(".ajs-modal")
+        )
+
+        status = self.page.find_by_xpath("//div[contains(@class,'bg-success')]").text
+
+        self.assertEquals(status, "Successfully completed.")
+        self.page.find_by_xpath("//span[contains(string(), 'Click here for details.')]").click()
+        command = self.page.find_by_xpath("//p[contains(@class, 'bg-detailed-desc')]").text
+
+        self.assertIn(self.server['name'], str(command))
+        self.assertIn("from database 'acceptance_test_db'", str(command))
+        self.assertIn("test_backup_file", str(command))
+        self.assertIn("pg_dump", str(command))
+
+        self.page.find_by_xpath("//div[contains(@class,'wcFloatingFocus')]//div[contains(@class,'fa-close')]").click()
+
+    def after(self):
+        self.page.remove_server(self.server)
+        connection = test_utils.get_db_connection(
+            self.server['db'],
+            self.server['username'],
+            self.server['db_password'],
+            self.server['host'],
+            self.server['port'],
+            self.server['sslmode']
+        )
+        test_utils.drop_database(connection, "acceptance_test_db")
diff --git a/web/pgadmin/tools/backup/tests/__init__.py b/web/pgadmin/tools/backup/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/web/pgadmin/tools/backup/tests/test_backup_message.py b/web/pgadmin/tools/backup/tests/test_backup_message.py
new file mode 100644
index 0000000..780106e
--- /dev/null
+++ b/web/pgadmin/tools/backup/tests/test_backup_message.py
@@ -0,0 +1,148 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import sys
+
+from flask import Response
+import simplejson as json
+
+from pgadmin.tools.backup import BackupMessage, BACKUP
+from pgadmin.utils.route import BaseTestGenerator
+
+if sys.version_info < (3, 3):
+    from mock import patch, MagicMock
+else:
+    from unittest.mock import patch, MagicMock
+
+
+class BackupMessageTest(BaseTestGenerator):
+    """Test the BackupMessage class"""
+    scenarios = [
+        ('When backup server',
+         dict(
+             class_params=dict(
+                 type=BACKUP.SERVER,
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 args=[
+                    '--file',
+                    "backup_file",
+                    '--host',
+                    "localhost",
+                    '--port',
+                    "5444",
+                    '--username',
+                    "postgres",
+                    '--no-password',
+                    '--database',
+                    "postgres"
+                ],
+                 cmd = "/test_path/pg_dump"
+             ),
+             extected_msg="Backing up the server 'test_backup_server (localhost:5444)'...",
+             expetced_details_cmd='/test_path/pg_dump --file "backup_file" --host "localhost"'
+                                  ' --port "5444" --username "postgres" --no-password --database "postgres"'
+
+         )),
+        ('When backup global',
+         dict(
+             class_params=dict(
+                 type=BACKUP.GLOBALS,
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 args=[
+                     '--file',
+                     'backup_file',
+                     '--host',
+                     'localhost',
+                     '--port',
+                     '5444',
+                     '--username',
+                     'postgres',
+                     '--no-password',
+                     '--database',
+                     'postgres'
+                 ],
+                 cmd="/test_path/pg_dump"
+             ),
+             extected_msg="Backing up the global objects on the server 'test_backup_server (localhost:5444)'...",
+             expetced_details_cmd='/test_path/pg_dump --file "backup_file" --host "localhost"'
+                                  ' --port "5444" --username "postgres" --no-password --database "postgres"'
+
+         )),
+        ('When backup object',
+         dict(
+             class_params=dict(
+                 type=BACKUP.OBJECT,
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 args=[
+                     '--file',
+                     'backup_file',
+                     '--host',
+                     'localhost',
+                     '--port',
+                     '5444',
+                     '--username',
+                     'postgres',
+                     '--no-password',
+                     '--database',
+                     'postgres'
+                 ],
+                 cmd="/test_path/pg_dump"
+             ),
+             extected_msg="Backing up an object on the server 'test_backup_server (localhost:5444)'"
+                          " from database 'postgres'...",
+             expetced_details_cmd='/test_path/pg_dump --file "backup_file" --host "localhost"'
+                                  ' --port "5444" --username "postgres" --no-password --database "postgres"'
+
+         ))
+    ]
+
+    @patch('pgadmin.tools.backup.Server')
+    @patch('pgadmin.tools.backup.current_user')
+    def runTest(self, current_user_mock, server_mock):
+        current_user_mock = 1
+
+        class TestMockServer():
+            def __init__(self, name, host, port):
+                self.name = name
+                self.host = host
+                self.port = port
+        mock_obj = TestMockServer(self.class_params['name'],
+                                  self.class_params['host'],
+                                  self.class_params['port'])
+        mock_result = server_mock.query.filter_by.return_value
+        mock_result.first.return_value = mock_obj
+
+        backup_obj = BackupMessage(
+            self.class_params['type'],
+            self.class_params['sid'],
+            self.class_params['bfile'],
+            *self.class_params['args'],
+            **{'database': self.class_params['database']}
+        )
+
+        # Check the expected message returned
+        assert backup_obj.message == self.extected_msg
+
+        # Check the command
+        obj_details = backup_obj.details(self.class_params['cmd'], self.class_params['args'])
+        self.assertIn(self.expetced_details_cmd, obj_details)
diff --git a/web/pgadmin/tools/backup/tests/test_batch_process.py b/web/pgadmin/tools/backup/tests/test_batch_process.py
new file mode 100644
index 0000000..aab5fd1
--- /dev/null
+++ b/web/pgadmin/tools/backup/tests/test_batch_process.py
@@ -0,0 +1,216 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import sys
+
+from flask import Response
+import simplejson as json
+
+from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
+from pgadmin.tools.backup import BackupMessage, BACKUP
+from pgadmin.utils.route import BaseTestGenerator
+from pickle import dumps, loads
+
+if sys.version_info < (3, 3):
+    from mock import patch, MagicMock
+else:
+    from unittest.mock import patch, MagicMock
+
+
+class BatchProcessTest(BaseTestGenerator):
+    """Test the BatchProcess class"""
+    scenarios = [
+        ('When backup server',
+         dict(
+             class_params=dict(
+                 type=BACKUP.SERVER,
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 username='postgres',
+                 bfile='test_backup',
+                 args=[
+                    '--file',
+                    "backup_file",
+                    '--host',
+                    "localhost",
+                    '--port',
+                    "5444",
+                    '--username',
+                    "postgres",
+                    '--no-password',
+                    '--database',
+                    "postgres"
+                ],
+                 cmd='backup_server'
+             )
+         )),
+        ('When backup globals',
+         dict(
+             class_params=dict(
+                 type=BACKUP.GLOBALS,
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 username='postgres',
+                 bfile='test_backup',
+                 args=[
+                     '--file',
+                     "backup_file",
+                     '--host',
+                     "localhost",
+                     '--port',
+                     "5444",
+                     '--username',
+                     "postgres",
+                     '--no-password',
+                     '--database',
+                     "postgres"
+                 ],
+                 cmd='backup'
+             )
+         )),
+        ('When backup object',
+         dict(
+             class_params=dict(
+                 type=BACKUP.OBJECT,
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 username='postgres',
+                 bfile='test_backup',
+                 args=[
+                     '--file',
+                     "backup_file",
+                     '--host',
+                     "localhost",
+                     '--port',
+                     "5444",
+                     '--username',
+                     "postgres",
+                     '--no-password',
+                     '--database',
+                     "postgres"
+                 ],
+                 cmd='backup'
+             )
+         ))
+    ]
+
+    @patch('pgadmin.misc.bgprocess.processes.Popen')
+    @patch('pgadmin.misc.bgprocess.processes.current_app')
+    @patch('pgadmin.misc.bgprocess.processes.db')
+    @patch('pgadmin.tools.backup.Server')
+    @patch('pgadmin.tools.backup.current_user')
+    @patch('pgadmin.misc.bgprocess.processes.current_user')
+    def runTest(self, current_user_mock, current_user, server_mock, db_mock,
+                current_app_mock, popen_mock):
+        current_user.id = 1
+        current_user_mock.id = 1
+        current_app_mock.PGADMIN_RUNTIME = False
+
+        class TestMockServer():
+            def __init__(self, name, host, port):
+                self.name = name
+                self.host = host
+                self.port = port
+
+        def db_session_add_mock(j):
+            cmd_obj = loads(j.desc)
+            assert isinstance(cmd_obj, IProcessDesc)
+            self.assertEquals(cmd_obj.backup_type, self.class_params['type'])
+            self.assertEquals(cmd_obj.bfile, self.class_params['bfile'])
+            self.assertEquals(cmd_obj.database, self.class_params['database'])
+            self.assertEquals(cmd_obj.cmd, ' --file "backup_file" --host "{0}" '
+                                           '--port "{1}" --username "{2}" '
+                                           '--no-password --database "{3}"'.format(
+                self.class_params['host'], self.class_params['port'],
+                self.class_params['username'], self.class_params['database']
+            ))
+
+        mock_obj = TestMockServer(self.class_params['name'],
+                                  self.class_params['host'],
+                                  self.class_params['port'])
+        mock_result = server_mock.query.filter_by.return_value
+        mock_result.first.return_value = mock_obj
+
+        db_mock.session.add.side_effect = db_session_add_mock
+
+        backup_obj = BackupMessage(
+            self.class_params['type'],
+            self.class_params['sid'],
+            self.class_params['bfile'],
+            *self.class_params['args'],
+            **{'database': self.class_params['database']}
+        )
+
+        p = BatchProcess(
+            desc=backup_obj,
+            cmd=self.class_params['cmd'],
+            args=self.class_params['args']
+        )
+
+        # Check that _create_process has been called
+        assert db_mock.session.add.called
+
+        # Check start method
+        self._check_start(popen_mock, p)
+
+        # Check list method
+        self._check_list(p, backup_obj)
+
+    def _check_start(self, popen_mock, p):
+        cmd_test = self.class_params['cmd']
+
+        class popenMockSideEffect():
+            def __init__(self, cmd, **kwargs):
+                assert cmd_test in cmd
+                assert 'env' in kwargs
+
+            def poll(self):
+                pass
+
+        popen_mock.side_effect = popenMockSideEffect
+        p.start()
+
+        assert popen_mock.called
+
+    @patch('pgadmin.misc.bgprocess.processes.Process')
+    @patch('pgadmin.misc.bgprocess.processes.BatchProcess.update_process_info')
+    def _check_list(self, p, backup_obj, update_process_info_mock, process_mock):
+        class TestMockProcess():
+            def __init__(self, desc, args, cmd):
+                self.pid = 1
+                self.exit_code = 1
+                self.start_time = '2018-04-17 06:18:56.315445 +0000'
+                self.end_time = None
+                self.desc = dumps(desc)
+                self.arguments = " ".join(args)
+                self.command = cmd
+                self.acknowledge = None
+
+        process_mock.query.filter_by.return_value = [TestMockProcess(backup_obj,
+                                                                    self.class_params['args'],
+                                                                    self.class_params['cmd'])]
+
+        update_process_info_mock.return_value = [True, True]
+
+        ret_value = p.list()
+        self.assertEqual(1, len(ret_value))
+        assert 'details' in ret_value[0]
+        assert 'desc' in ret_value[0]
+
+
+
+
diff --git a/web/pgadmin/tools/backup/tests/test_create_backup_job.py b/web/pgadmin/tools/backup/tests/test_create_backup_job.py
new file mode 100644
index 0000000..6c6e58e
--- /dev/null
+++ b/web/pgadmin/tools/backup/tests/test_create_backup_job.py
@@ -0,0 +1,371 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import sys
+import time
+import random
+import config
+
+from flask import Response
+import simplejson as json
+from pickle import dumps, loads
+
+
+from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
+from pgadmin.tools.backup import BackupMessage, BACKUP
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+from pgadmin.utils import server_utils as server_utils
+from pgadmin.browser.server_groups.servers.databases.tests import utils as \
+    database_utils
+
+from flask import current_app
+
+if sys.version_info < (3, 3):
+    from mock import patch, MagicMock
+else:
+    from unittest.mock import patch, MagicMock
+
+
+class BackupJobTest(BaseTestGenerator):
+    """Backup api test cases"""
+    scenarios = [
+        ('When backup the object with the default options',
+         dict(
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 blobs=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres'
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--format=c', '--blobs'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=0
+         )),
+        ('When backup the object with option sections to all data',
+         dict(
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 data=True,
+                 pre_data=True,
+                 post_data=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--format=c',
+                                '--section=pre-data', '--section=data',
+                                '--section=post-data'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=0
+
+         )),
+        ('When backup the object with option only_data',
+         dict(
+             params=dict(
+                 file='test_backup_file',
+                 format='plain',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 only_data=True,
+                 only_schema=False
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--format=p', '--data-only'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=0
+         )),
+        ('When backup the object with option only_data',
+         dict(
+             params=dict(
+                 file='test_backup_file',
+                 format='plain',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 only_data=True,
+                 only_schema=True,
+                 dns_owner=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--format=p', '--data-only'],
+             not_expected_cmd_opts=['--schema-only', '--no-owner'],
+             expected_exit_code=0
+         )),
+        ('When backup the object with option only_schema',
+         dict(
+             params=dict(
+                 file='test_backup_file',
+                 format='plain',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 only_data=False,
+                 only_schema=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--format=p', '--schema-only'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=0
+         )),
+        ('When backup the object with option - format plain and dns_owner',
+         dict(
+             params=dict(
+                 file='test_backup_file',
+                 format='plain',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 dns_owner=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--format=p', '--no-owner'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=0
+         )),
+        ('When backup the object with option - Do not save privilege,'
+         ' tablespace, unlogged table data',
+         dict(
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 dns_privilege=True,
+                 dns_unlogged_tbl_data=True,
+                 dns_tablespace=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--no-privileges',
+                                '--no-tablespaces',
+                                '--no-unlogged-table-data'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=0
+         )),
+        ('When backup the object with option - all queries',
+         dict(
+             params=dict(
+                 file='test_backup_file',
+                 format='plain',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 use_column_inserts=True,
+                 include_create_database=True,
+                 use_insert_commands=True,
+                 include_drop_database=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--create', '--clean', '--inserts',
+                                '--column-inserts'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=0
+         )),
+        ('When backup the object with option - all queries and format custom',
+         dict(
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 use_column_inserts=True,
+                 include_create_database=True,
+                 use_insert_commands=True,
+                 include_drop_database=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--inserts',
+                                '--column-inserts'],
+             not_expected_cmd_opts=['--create', '--clean'],
+             expected_exit_code=0
+         )),
+        ('When backup the object with option - miscellaneous',
+         dict(
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 disable_quoting=True,
+                 use_set_session_auth=True,
+                 with_oids=True,
+                 dqoute=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--quote-all',
+                                '--disable-dollar-quoting', '--oids',
+                                '--use-set-session-authorization'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=0
+         )),
+        ('When backup the object with format tar',
+         dict(
+             params=dict(
+                 file='test_backup_file',
+                 format='tar',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 blobs=True,
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose',
+                                '--blobs',
+                                '--format=t'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=0
+         )),
+        ('When backup the server',
+         dict(
+             params=dict(
+                 file='test_backup_server_file',
+                 dqoute=False,
+                 verbose=True,
+                 type='server'
+             ),
+             url='/backup/job/{0}',
+             expected_cmd_opts=['--verbose'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=None
+         )),
+        ('When backup globals',
+         dict(
+             params=dict(
+                 file='test_backup_global_file',
+                 dqoute=False,
+                 verbose=True,
+                 type='globals'
+             ),
+             url='/backup/job/{0}',
+             expected_cmd_opts=['--verbose'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=None
+         ))
+    ]
+
+    def runTest(self):
+        self.db_name = ''
+        self.server_id = parent_node_dict["server"][-1]["server_id"]
+        server_response = server_utils.connect_server(self, self.server_id)
+        if server_response["info"] == "Server connected.":
+            db_owner = server_response['data']['user']['name']
+            self.data = database_utils.get_db_data(db_owner)
+            self.db_name = self.data['name']
+
+        url = self.url.format(self.server_id)
+
+        # Create the backup job
+        response = self.tester.post(url,
+                                    data=json.dumps(self.params),
+                                    content_type='html/json')
+        self.assertEquals(response.status_code, 200)
+        response_data = json.loads(response.data.decode('utf-8'))
+        job_id = response_data['data']['job_id']
+
+        cnt = 0
+        while 1:
+            if cnt > 1:
+                break
+            # Check the process list
+            response1 = self.tester.get('/misc/bgprocess/?_='.format(random.randint(1, 9999999)))
+            self.assertEquals(response1.status_code, 200)
+            process_list = json.loads(response1.data.decode('utf-8'))
+
+            if len(process_list) > 0 and 'execution_time' in process_list[0]:
+                break
+            time.sleep(0.5)
+            cnt += 1
+
+        assert 'execution_time' in process_list[0]
+        assert 'stime' in process_list[0]
+        assert 'exit_code' in process_list[0]
+        self.assertEqual(self.expected_exit_code, process_list[0]['exit_code'])
+        if self.expected_cmd_opts:
+            for opt in self.expected_cmd_opts:
+                self.assertIn(opt, process_list[0]['details'])
+        if self.not_expected_cmd_opts:
+            for opt in self.not_expected_cmd_opts:
+                self.assertNotIn(opt, process_list[0]['details'])
+
+
+        # Check the process details
+        p_details = self.tester.get('/misc/bgprocess/{0}?_='.format(
+            job_id, random.randint(1, 9999999))
+        )
+        self.assertEquals(p_details.status_code, 200)
+        p_details_data = json.loads(p_details.data.decode('utf-8'))
+
+        p_details = self.tester.get('/misc/bgprocess/{0}/{1}/{2}/?_='.format(
+            job_id, 0, 0, random.randint(1, 9999999))
+        )
+        self.assertEquals(p_details.status_code, 200)
+        p_details_data = json.loads(p_details.data.decode('utf-8'))
+
+        # Retrieve the backup job process logs
+        while 1:
+            out, err, status = BackupJobTest.get_params(p_details_data)
+            if status:
+                break
+
+            p_details = self.tester.get('/misc/bgprocess/{0}/{1}/{2}/?_={3}'.format(
+                job_id, out, err, random.randint(1, 9999999))
+            )
+            self.assertEquals(p_details.status_code, 200)
+            p_details_data = json.loads(p_details.data.decode('utf-8'))
+
+            time.sleep(1)
+
+        # Check the job is complete.
+        backup_ack = self.tester.put('/misc/bgprocess/{0}'.format(job_id))
+        self.assertEquals(backup_ack.status_code, 200)
+        backup_ack_res = json.loads(backup_ack.data.decode('utf-8'))
+
+        self.assertEquals(backup_ack_res['success'], 1)
+
+    @staticmethod
+    def get_params(data):
+        out = 0
+        out_done = False
+        err = 0
+        err_done = False
+        if 'out' in data:
+            out = data['out'] and data['out']['pos']
+
+            if 'done' in data['out']:
+                out_done = data['out']['done']
+
+        if 'err' in data:
+            err = data['err'] and data['err']['pos']
+
+            if 'done' in data['err']:
+                err_done = data['err']['done']
+
+        return out, err, (out_done and err_done)
+
+
diff --git a/web/regression/runtests.py b/web/regression/runtests.py
index 1de9823..99846c1 100644
--- a/web/regression/runtests.py
+++ b/web/regression/runtests.py
@@ -72,6 +72,13 @@ config.UPGRADE_CHECK_ENABLED = False
 
 pgadmin_credentials = test_setup.config_data
 
+config.DEFAULT_BINARY_PATHS = {
+    "pg": pgadmin_credentials['DEFAULT_BINARY_PATHS']['pg'],
+    "ppas": pgadmin_credentials['DEFAULT_BINARY_PATHS']['ppas'],
+    "gpdb": ""
+}
+
+
 # Set environment variables for email and password
 os.environ['PGADMIN_SETUP_EMAIL'] = ''
 os.environ['PGADMIN_SETUP_PASSWORD'] = ''
@@ -112,6 +119,9 @@ test_client = app.test_client()
 driver = None
 app_starter = None
 handle_cleanup = None
+app.PGADMIN_RUNTIME = True
+if config.SERVER_MODE is True:
+    app.PGADMIN_RUNTIME = False
 
 setattr(unit_test.result.TestResult, "passed", [])
 
diff --git a/web/regression/test_config.json.in b/web/regression/test_config.json.in
index 47f8499..41f4dd0 100644
--- a/web/regression/test_config.json.in
+++ b/web/regression/test_config.json.in
@@ -28,5 +28,9 @@
     {
       "comment": "This is test update comment"
     }
-  ]
+  ],
+  "DEFAULT_BINARY_PATHS": {
+     "pg": "",
+     "ppas": ""
+  }
 }

---

From: Joao De Almeida Pereira <[email-masked]>
Date: Wed, 25 Apr 2018 16:10:52 +0000

Hi Khushboo,

We reviewed the patch and it is very nice to see some more coverage in this
area. Good job :D

We passed the tests through our CI the feature tests are not passing, but
the linter fails:

./pgadmin/feature_tests/pg_utilities_backup_test.py:37: [E501] line
too long (91 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:265>
./pgadmin/feature_tests/pg_utilities_backup_test.py:53: [E501] line
too long (104 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:266>
./pgadmin/feature_tests/pg_utilities_backup_test.py:59: [E501] line
too long (85 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:267>
./pgadmin/feature_tests/pg_utilities_backup_test.py:62: [E501] line
too long (96 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:268>
./pgadmin/feature_tests/pg_utilities_backup_test.py:63: [E501] line
too long (91 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:269>
./pgadmin/feature_tests/pg_utilities_backup_test.py:70: [E501] line
too long (118 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:270>
./pgadmin/tools/backup/tests/test_backup_message.py:37: [E121]
continuation line under-indented for hanging indent
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:271>
./pgadmin/tools/backup/tests/test_backup_message.py:48: [E122]
continuation line missing indentation or outdented
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:272>
./pgadmin/tools/backup/tests/test_backup_message.py:49: [E251]
unexpected spaces around keyword / parameter equals
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:273>
./pgadmin/tools/backup/tests/test_backup_message.py:49: [E251]
unexpected spaces around keyword / parameter equals
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:274>
./pgadmin/tools/backup/tests/test_backup_message.py:51: [E501] line
too long (91 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:275>
./pgadmin/tools/backup/tests/test_backup_message.py:52: [E501] line
too long (94 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:276>
./pgadmin/tools/backup/tests/test_backup_message.py:53: [E501] line
too long (108 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:277>
./pgadmin/tools/backup/tests/test_backup_message.py:81: [E501] line
too long (113 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:278>
./pgadmin/tools/backup/tests/test_backup_message.py:82: [E501] line
too long (94 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:279>
./pgadmin/tools/backup/tests/test_backup_message.py:83: [E501] line
too long (108 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:280>
./pgadmin/tools/backup/tests/test_backup_message.py:111: [E501] line
too long (100 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:281>
./pgadmin/tools/backup/tests/test_backup_message.py:113: [E501] line
too long (94 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:282>
./pgadmin/tools/backup/tests/test_backup_message.py:114: [E501] line
too long (108 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:283>
./pgadmin/tools/backup/tests/test_backup_message.py:147: [E501] line
too long (93 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:284>
./pgadmin/tools/backup/tests/test_batch_process.py:40: [E121]
continuation line under-indented for hanging indent
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:285>
./pgadmin/tools/backup/tests/test_batch_process.py:51: [E122]
continuation line missing indentation or outdented
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:286>
./pgadmin/tools/backup/tests/test_batch_process.py:135: [E501] line
too long (80 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:287>
./pgadmin/tools/backup/tests/test_batch_process.py:137: [E501] line
too long (83 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:288>
./pgadmin/tools/backup/tests/test_batch_process.py:138: [E122]
continuation line missing indentation or outdented
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:289>
./pgadmin/tools/backup/tests/test_batch_process.py:139: [E122]
continuation line missing indentation or outdented
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:290>
./pgadmin/tools/backup/tests/test_batch_process.py:140: [E122]
continuation line missing indentation or outdented
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:291>
./pgadmin/tools/backup/tests/test_batch_process.py:191: [E501] line
too long (81 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:292>
./pgadmin/tools/backup/tests/test_batch_process.py:203: [E501] line
too long (80 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:293>
./pgadmin/tools/backup/tests/test_batch_process.py:204: [E128]
continuation line under-indented for visual indent
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:294>
./pgadmin/tools/backup/tests/test_batch_process.py:204: [E501] line
too long (94 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:295>
./pgadmin/tools/backup/tests/test_batch_process.py:205: [E128]
continuation line under-indented for visual indent
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:296>
./pgadmin/tools/backup/tests/test_batch_process.py:205: [E501] line
too long (94 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:297>
./pgadmin/tools/backup/tests/test_batch_process.py:216: [W391] blank
line at end of file
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:298>
./pgadmin/tools/backup/tests/test_create_backup_job.py:296: [E501]
line too long (97 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:299>
./pgadmin/tools/backup/tests/test_create_backup_job.py:317: [E303] too
many blank lines (2)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:300>
./pgadmin/tools/backup/tests/test_create_backup_job.py:336: [E501]
line too long (84 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:301>
./pgadmin/tools/backup/tests/test_create_backup_job.py:371: [W391]
blank line at end of file
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:302>
2       E121 continuation line under-indented for hanging indent
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:303>
5       E122 continuation line missing indentation or outdented
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:304>
2       E128 continuation line under-indented for visual indent
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:305>
2       E251 unexpected spaces around keyword / parameter equals
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:306>
1       E303 too many blank lines (2)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:307>
24      E501 line too long (91 > 79 characters)
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:308>
2       W391 blank line at end of file
 <https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-linter/builds/17#L5ad0f3d8:309>
38

For the feature tests, we realized we had to update the configuration, and
we did that, but we get the following error attached. We spent some time
trying to understand the problem but we were not successful.

Codewise:
- We just found some One Letter Variables in the code...
- Looks like there is a bug report in this area of the code and we do not
have coverage for it: https://redmine.postgresql.org/issues/3232
  Looks like in some of the unit tests we only have happy path tests, maybe
we should see if there are any sad paths that also need coverage.

The configuration change, maybe need to be updated. When we install
multiple versions of postgres the binaries live in
`/usr/lib/postgresql/{{db_version}}/bin`, which makes us think that this
configuration should live near the server configuration, maybe? Also to
maintain coherency on the naming maybe we should make it all lower case.
Just as an aside, you can add the gpdb configuration as well in you patch.

Thanks
Victoria & Joao

---

From: Khushboo Vashi <[email-masked]>
Date: Mon, 28 May 2018 17:39:36 +0530

Hi,

please find the attached updated patch for the test cases of Backup,
Restore and Maintenance modules which includes:

1. Unit test cases

Thanks,
Khushboo

On Wed, Apr 25, 2018 at 9:40 PM, Joao De Almeida Pereira <
[email-masked]> wrote:

> Hi Khushboo,
>
> We reviewed the patch and it is very nice to see some more coverage in
> this area. Good job :D
>
> ./pgadmin/feature_tests/pg_utilities_backup_test.py:37: [E501] line too long (91 > 79 characters)
> ./pgadmin/feature_tests/pg_utilities_backup_test.py:53: [E501] line too long (104 > 79 characters)
> ./pgadmin/feature_tests/pg_utilities_backup_test.py:59: [E501] line too long (85 > 79 characters)
> ./pgadmin/feature_tests/pg_utilities_backup_test.py:62: [E501] line too long (96 > 79 characters)
> ./pgadmin/feature_tests/pg_utilities_backup_test.py:63: [E501] line too long (91 > 79 characters)
> ./pgadmin/feature_tests/pg_utilities_backup_test.py:70: [E501] line too long (118 > 79 characters)
> ./pgadmin/tools/backup/tests/test_backup_message.py:37: [E121] continuation line under-indented for hanging indent
> ./pgadmin/tools/backup/tests/test_backup_message.py:48: [E122] continuation line missing indentation or outdented
> ./pgadmin/tools/backup/tests/test_backup_message.py:49: [E251] unexpected spaces around keyword / parameter equals
> ./pgadmin/tools/backup/tests/test_backup_message.py:49: [E251] unexpected spaces around keyword / parameter equals
> ./pgadmin/tools/backup/tests/test_backup_message.py:51: [E501] line too long (91 > 79 characters)
> ./pgadmin/tools/backup/tests/test_backup_message.py:52: [E501] line too long (94 > 79 characters)
> ./pgadmin/tools/backup/tests/test_backup_message.py:53: [E501] line too long (108 > 79 characters)
> ./pgadmin/tools/backup/tests/test_backup_message.py:81: [E501] line too long (113 > 79 characters)
> ./pgadmin/tools/backup/tests/test_backup_message.py:82: [E501] line too long (94 > 79 characters)
> ./pgadmin/tools/backup/tests/test_backup_message.py:83: [E501] line too long (108 > 79 characters)
> ./pgadmin/tools/backup/tests/test_backup_message.py:111: [E501] line too long (100 > 79 characters)
> ./pgadmin/tools/backup/tests/test_backup_message.py:113: [E501] line too long (94 > 79 characters)
> ./pgadmin/tools/backup/tests/test_backup_message.py:114: [E501] line too long (108 > 79 characters)
> ./pgadmin/tools/backup/tests/test_backup_message.py:147: [E501] line too long (93 > 79 characters)
> ./pgadmin/tools/backup/tests/test_batch_process.py:40: [E121] continuation line under-indented for hanging indent
> ./pgadmin/tools/backup/tests/test_batch_process.py:51: [E122] continuation line missing indentation or outdented
> ./pgadmin/tools/backup/tests/test_batch_process.py:135: [E501] line too long (80 > 79 characters)
> ./pgadmin/tools/backup/tests/test_batch_process.py:137: [E501] line too long (83 > 79 characters)
> ./pgadmin/tools/backup/tests/test_batch_process.py:138: [E122] continuation line missing indentation or outdented
> ./pgadmin/tools/backup/tests/test_batch_process.py:139: [E122] continuation line missing indentation or outdented
> ./pgadmin/tools/backup/tests/test_batch_process.py:140: [E122] continuation line missing indentation or outdented
> ./pgadmin/tools/backup/tests/test_batch_process.py:191: [E501] line too long (81 > 79 characters)
> ./pgadmin/tools/backup/tests/test_batch_process.py:203: [E501] line too long (80 > 79 characters)
> ./pgadmin/tools/backup/tests/test_batch_process.py:204: [E128] continuation line under-indented for visual indent
> ./pgadmin/tools/backup/tests/test_batch_process.py:204: [E501] line too long (94 > 79 characters)
> ./pgadmin/tools/backup/tests/test_batch_process.py:205: [E128] continuation line under-indented for visual indent
> ./pgadmin/tools/backup/tests/test_batch_process.py:205: [E501] line too long (94 > 79 characters)
> ./pgadmin/tools/backup/tests/test_batch_process.py:216: [W391] blank line at end of file
> ./pgadmin/tools/backup/tests/test_create_backup_job.py:296: [E501] line too long (97 > 79 characters)
> ./pgadmin/tools/backup/tests/test_create_backup_job.py:317: [E303] too many blank lines (2)
> ./pgadmin/tools/backup/tests/test_create_backup_job.py:336: [E501] line too long (84 > 79 characters)
> ./pgadmin/tools/backup/tests/test_create_backup_job.py:371: [W391] blank line at end of file
>   Looks like in some of the unit tests we only have happy path tests,
> maybe we should see if there are any sad paths that also need coverage.
>
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_add.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_add.py
index 5ad0469..c3be213 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_add.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_add.py
@@ -36,5 +36,5 @@ class ServersAddTestCase(BaseTestGenerator):
         utils.write_node_info("sid", server_dict)
 
     def tearDown(self):
-        """This function delete the server from SQLite """
+        """This function delete the server from SQLite"""
         utils.delete_server_with_api(self.tester, self.server_id)
diff --git a/web/pgadmin/browser/server_groups/servers/types.py b/web/pgadmin/browser/server_groups/servers/types.py
index d0bea4f..159c860 100644
--- a/web/pgadmin/browser/server_groups/servers/types.py
+++ b/web/pgadmin/browser/server_groups/servers/types.py
@@ -61,7 +61,6 @@ class ServerType(object):
         for key in cls.registry:
             st = cls.registry[key]
             default_path = config.DEFAULT_BINARY_PATHS.get(st.stype, "")
-
             st.utility_path = paths.register(
                 'bin_paths', st.stype + '_bin_dir',
                 st.UTILITY_PATH_LABEL,
diff --git a/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py b/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py
new file mode 100644
index 0000000..c8cbe28
--- /dev/null
+++ b/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py
@@ -0,0 +1,127 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+import time
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support import expected_conditions as EC
+from regression.feature_utils.base_feature_test import BaseFeatureTest
+from regression.python_test_utils import test_utils
+
+import config
+
+
+class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
+    """ This class test PG utilities - Backup and Restore test scenarios """
+
+    scenarios = [
+        ("Test for PG utilities - Backup and Restore", dict())
+    ]
+
+    def before(self):
+        if self.server['DEFAULT_BINARY_PATHS'] is None:
+            self.skipTest(
+                "DEFAULT_BINARY_PATHS is not set for the server {0}".format(
+                    self.server['name']
+                )
+            )
+        connection = test_utils.get_db_connection(
+            self.server['db'],
+            self.server['username'],
+            self.server['db_password'],
+            self.server['host'],
+            self.server['port'],
+            self.server['sslmode']
+        )
+        test_utils.drop_database(connection, "pg_utility_test_db")
+
+        test_utils.create_database(self.server, "pg_utility_test_db")
+        self.page.add_server(self.server)
+
+        self.wait = WebDriverWait(self.page.driver, 10)
+
+    def runTest(self):
+        self.page.toggle_open_server(self.server['name'])
+        self.page.toggle_open_tree_item('Databases')
+        self.page.toggle_open_tree_item('pg_utility_test_db')
+        self.driver.find_element_by_link_text("Tools").click()
+
+        self.page.find_by_partial_link_text("Backup...").click()
+
+        self.wait.until(
+            EC.element_to_be_clickable((By.NAME, 'file'))
+        )
+
+        self.page.fill_input_by_field_name("file", "test_backup_file")
+        self.page.find_by_xpath("//button[contains(@class,'fa-save') "
+                                "and contains(.,'Backup')]").click()
+
+        self.page.wait_for_element_to_disappear(
+            lambda driver: driver.find_element_by_css_selector(".ajs-modal")
+        )
+
+        status = self.page.find_by_xpath("//div[contains(@class,"
+                                         "'bg-success')]").text
+
+        self.assertEquals(status, "Successfully completed.")
+        self.page.find_by_xpath("//span[contains(string(), "
+                                "'Click here for details.')]").click()
+        command = self.page.find_by_xpath("//p[contains(@class, "
+                                          "'bg-detailed-desc')]").text
+
+        self.assertIn(self.server['name'], str(command))
+        self.assertIn("from database 'pg_utility_test_db'", str(command))
+        self.assertIn("test_backup_file", str(command))
+        self.assertIn("pg_dump", str(command))
+
+        self.page.find_by_xpath("//div[contains(@class,'wcFloatingFocus')"
+                                "]//div[contains(@class,'fa-close')]").click()
+
+        self.driver.find_element_by_link_text("Tools").click()
+        self.page.find_by_partial_link_text("Restore...").click()
+
+        self.wait.until(
+            EC.element_to_be_clickable((By.NAME, 'file'))
+        )
+
+        self.page.fill_input_by_field_name("file", "test_backup_file")
+        self.page.find_by_xpath("//button[contains(@class,'fa-upload')"
+                                " and contains(.,'Restore')]").click()
+
+        self.page.wait_for_element_to_disappear(
+            lambda driver: driver.find_element_by_css_selector(".ajs-modal")
+        )
+
+        status = self.page.find_by_xpath("//div[contains(@class,"
+                                         "'bg-success')]").text
+
+        self.assertEquals(status, "Successfully completed.")
+        self.page.find_by_xpath("//span[contains(string(),"
+                                " 'Click here for details.')]").click()
+        command = self.page.find_by_xpath("//p[contains(@class,"
+                                          " 'bg-detailed-desc')]").text
+
+        self.assertIn(self.server['name'], str(command))
+        self.assertIn("test_backup_file", str(command))
+        self.assertIn("pg_restore", str(command))
+
+        self.page.find_by_xpath("//div[contains(@class,'wcFloatingFocus')]"
+                                "//div[contains(@class,'fa-close')]").click()
+
+    def after(self):
+        self.page.remove_server(self.server)
+        connection = test_utils.get_db_connection(
+            self.server['db'],
+            self.server['username'],
+            self.server['db_password'],
+            self.server['host'],
+            self.server['port'],
+            self.server['sslmode']
+        )
+        test_utils.drop_database(connection, "pg_utility_test_db")
diff --git a/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py b/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py
new file mode 100644
index 0000000..83f3736
--- /dev/null
+++ b/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py
@@ -0,0 +1,112 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+# _*_  coding: utf-8 _*_
+import time
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support import expected_conditions as EC
+from regression.feature_utils.base_feature_test import BaseFeatureTest
+from regression.python_test_utils import test_utils
+
+
+class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
+    """ This class test PG utilities test scenarios """
+
+    scenarios = [
+        ("Test for PG maintenance: database pg_maintenance", dict(
+            database_name='pg_maintenance',
+            table_name='pg_maintenance_table',
+            test_level='database'
+        )),
+        ("Test for PG maintenance: database", dict(
+            database_name='pg_maintenance',
+            table_name='pg_maintenance_table',
+            test_level='table'
+        )),
+    ]
+
+    def before(self):
+        if self.server['DEFAULT_BINARY_PATHS'] is None:
+            self.skipTest(
+                "DEFAULT_BINARY_PATHS is not set for the server {0}".format(
+                    self.server['name']
+                )
+            )
+        connection = test_utils.get_db_connection(
+            self.server['db'],
+            self.server['username'],
+            self.server['db_password'],
+            self.server['host'],
+            self.server['port'],
+            self.server['sslmode']
+        )
+        test_utils.create_database(self.server, self.database_name)
+        test_utils.create_table(self.server, self.database_name,
+                                self.table_name)
+        self.page.add_server(self.server)
+        self.wait = WebDriverWait(self.page.driver, 10)
+
+    def runTest(self):
+        self._open_maintenance_dialogue()
+        # time.sleep
+        self.page.find_by_xpath("//button[contains(@class,'fa-save') and"
+                                " contains(.,'OK')]").click()
+        self.page.wait_for_element_to_disappear(
+            lambda driver: driver.find_element_by_css_selector(".ajs-modal")
+        )
+        self._verify_command()
+
+    def _open_maintenance_dialogue(self):
+        self.page.toggle_open_server(self.server['name'])
+        self.page.toggle_open_tree_item('Databases')
+        self.page.toggle_open_tree_item(self.database_name)
+        if self.test_level == 'table':
+            self.page.toggle_open_tree_item('Schemas')
+            self.page.toggle_open_tree_item('public')
+            self.page.toggle_open_tree_item('Tables')
+            self.page.find_by_xpath(
+                "//*[@id='tree']//"
+                "*[.='" + self.table_name + "']/../*[@class='aciTreeItem'"
+                                            "]").click()
+        self.driver.find_element_by_link_text("Tools").click()
+        self.page.find_by_partial_link_text("Maintenance...").click()
+        time.sleep(0.5)
+
+    def _verify_command(self):
+        status = self.page.find_by_xpath("//div[contains(@class,"
+                                         "'bg-success')]").text
+        self.assertEquals(status, "Successfully completed.")
+        self.page.find_by_xpath("//span[contains(string(),"
+                                " 'Click here for details.')]").click()
+        command = self.page.find_by_xpath("//p[contains(@class,"
+                                          " 'bg-detailed-desc')]").text
+        if self.test_level == 'database':
+            self.assertEquals(command, "VACUUM "
+                                       "(VERBOSE)\nRunning Query:"
+                                       "\nVACUUM VERBOSE;")
+        else:
+            self.assertEquals(command, "VACUUM "
+                                       "(VERBOSE)\nRunning Query:"
+                                       "\nVACUUM VERBOSE"
+                                       " public." + self.table_name + ";")
+
+        self.page.find_by_xpath("//div[contains(@class,'wcFloatingFocus')]//"
+                                "div[contains(@class,'fa-close')]").click()
+
+    def after(self):
+        self.page.remove_server(self.server)
+        connection = test_utils.get_db_connection(
+            self.server['db'],
+            self.server['username'],
+            self.server['db_password'],
+            self.server['host'],
+            self.server['port'],
+            self.server['sslmode']
+        )
+        test_utils.drop_database(connection, self.database_name)
diff --git a/web/pgadmin/tools/backup/tests/__init__.py b/web/pgadmin/tools/backup/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/web/pgadmin/tools/backup/tests/test_backup_create_job_unit_test.py b/web/pgadmin/tools/backup/tests/test_backup_create_job_unit_test.py
new file mode 100644
index 0000000..1ff608b
--- /dev/null
+++ b/web/pgadmin/tools/backup/tests/test_backup_create_job_unit_test.py
@@ -0,0 +1,458 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+
+import sys
+import simplejson as json
+
+from pgadmin.misc.bgprocess.processes import BatchProcess
+from pgadmin.tools.backup import BackupMessage
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+from pgadmin.utils import server_utils as server_utils
+from pgadmin.browser.server_groups.servers.databases.tests import utils as \
+    database_utils
+
+
+if sys.version_info < (3, 3):
+    from mock import patch, MagicMock
+else:
+    from unittest.mock import patch, MagicMock
+
+
+class BackupCreateJobTest(BaseTestGenerator):
+    """Test the BackupCreateJob class"""
+    scenarios = [
+        ('When backup object with default options',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 blobs=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres'
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--format=c', '--blobs'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When backup the object with option sections to all data',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 data=True,
+                 pre_data=True,
+                 post_data=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--format=c',
+                                '--section=pre-data', '--section=data',
+                                '--section=post-data'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When backup the object with option only_data',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='plain',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 only_data=True,
+                 only_schema=False
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--format=p', '--data-only'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When backup the object with option only_data',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='plain',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 only_data=True,
+                 only_schema=True,
+                 dns_owner=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--format=p', '--data-only'],
+             not_expected_cmd_opts=['--schema-only', '--no-owner'],
+             expected_exit_code=[0, None]
+         )),
+        ('When backup the object with option only_schema',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='plain',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 only_data=False,
+                 only_schema=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--format=p', '--schema-only'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When backup the object with option - format plain and dns_owner',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='plain',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 dns_owner=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--format=p', '--no-owner'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When backup the object with option - Do not save privilege,'
+         ' tablespace, unlogged table data',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 dns_privilege=True,
+                 dns_unlogged_tbl_data=True,
+                 dns_tablespace=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--no-privileges',
+                                '--no-tablespaces',
+                                '--no-unlogged-table-data'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When backup the object with option - all queries',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='plain',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 use_column_inserts=True,
+                 include_create_database=True,
+                 use_insert_commands=True,
+                 include_drop_database=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--create', '--clean', '--inserts',
+                                '--column-inserts'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When backup the object with option - all queries and format custom',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 use_column_inserts=True,
+                 include_create_database=True,
+                 use_insert_commands=True,
+                 include_drop_database=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--inserts',
+                                '--column-inserts'],
+             not_expected_cmd_opts=['--create', '--clean'],
+             expected_exit_code=[0, None]
+         )),
+        ('When backup the object with option - miscellaneous',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 disable_quoting=True,
+                 use_set_session_auth=True,
+                 with_oids=True,
+                 dqoute=True
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose', '--quote-all-identifiers',
+                                '--disable-dollar-quoting', '--oids',
+                                '--use-set-session-authorization'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When backup the object with format tar',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='tar',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 blobs=True,
+             ),
+             url='/backup/job/{0}/object',
+             expected_cmd_opts=['--verbose',
+                                '--blobs',
+                                '--format=t'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When backup the server',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_server_file',
+                 dqoute=False,
+                 verbose=True,
+                 type='server'
+             ),
+             url='/backup/job/{0}',
+             expected_cmd_opts=['--verbose'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When backup globals',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_global_file',
+                 dqoute=False,
+                 verbose=True,
+                 type='globals'
+             ),
+             url='/backup/job/{0}',
+             expected_cmd_opts=['--verbose'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         ))
+    ]
+
+    def setUp(self):
+        if self.server['DEFAULT_BINARY_PATHS'] is None:
+            self.skipTest(
+                "DEFAULT_BINARY_PATHS is not set for the server {0}".format(
+                    self.server['name']
+                )
+            )
+
+    @patch('pgadmin.tools.backup.Server')
+    @patch('pgadmin.tools.backup.current_user')
+    @patch('pgadmin.tools.backup.BackupMessage')
+    @patch('pgadmin.tools.backup.filename_with_file_manager_path')
+    @patch('pgadmin.tools.backup.BatchProcess')
+    def runTest(self, batch_process_mock, filename_mock,
+                backup_message_mock, current_user_mock, server_mock):
+        class TestMockServer():
+            def __init__(self, name, host, port, id, username,
+                         maintenance_db):
+                self.name = name
+                self.host = host
+                self.port = port
+                self.id = id
+                self.username = username
+                self.maintenance_db = maintenance_db
+
+        self.db_name = ''
+        self.server_id = parent_node_dict["server"][-1]["server_id"]
+        mock_obj = TestMockServer(self.class_params['name'],
+                                  self.class_params['host'],
+                                  self.class_params['port'],
+                                  self.server_id,
+                                  self.class_params['username'],
+                                  self.class_params['database']
+                                  )
+        mock_result = server_mock.query.filter_by.return_value
+        mock_result.first.return_value = mock_obj
+
+        filename_mock.return_value = self.params['file']
+
+        batch_process_mock.set_env_variables = MagicMock(
+            return_value=True
+        )
+        batch_process_mock.start = MagicMock(
+            return_value=True
+        )
+
+        server_response = server_utils.connect_server(self, self.server_id)
+        if server_response["info"] == "Server connected.":
+            db_owner = server_response['data']['user']['name']
+            self.data = database_utils.get_db_data(db_owner)
+            self.db_name = self.data['name']
+
+        url = self.url.format(self.server_id)
+
+        # Create the backup job
+        response = self.tester.post(url,
+                                    data=json.dumps(self.params),
+                                    content_type='html/json')
+        self.assertEquals(response.status_code, 200)
+        response_data = json.loads(response.data.decode('utf-8'))
+        job_id = response_data['data']['job_id']
+
+        assert backup_message_mock.called
+        assert batch_process_mock.called
+
+        if self.expected_cmd_opts:
+            for opt in self.expected_cmd_opts:
+                self.assertIn(
+                    opt,
+                    batch_process_mock.call_args_list[0][1]['args']
+                )
+        if self.not_expected_cmd_opts:
+            for opt in self.not_expected_cmd_opts:
+                self.assertNotIn(
+                    opt,
+                    batch_process_mock.call_args_list[0][1]['args']
+                )
diff --git a/web/pgadmin/tools/backup/tests/test_backup_message.py b/web/pgadmin/tools/backup/tests/test_backup_message.py
new file mode 100644
index 0000000..761d286
--- /dev/null
+++ b/web/pgadmin/tools/backup/tests/test_backup_message.py
@@ -0,0 +1,158 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import sys
+
+from flask import Response
+import simplejson as json
+
+from pgadmin.tools.backup import BackupMessage, BACKUP
+from pgadmin.utils.route import BaseTestGenerator
+
+if sys.version_info < (3, 3):
+    from mock import patch, MagicMock
+else:
+    from unittest.mock import patch, MagicMock
+
+
+class BackupMessageTest(BaseTestGenerator):
+    """Test the BackupMessage class"""
+    scenarios = [
+        ('When Backup server',
+         dict(
+             class_params=dict(
+                 type=BACKUP.SERVER,
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_restore',
+                 args=[
+                     '--file',
+                     "backup_file",
+                     '--host',
+                     "localhost",
+                     '--port',
+                     "5444",
+                     '--username',
+                     "postgres",
+                     '--no-password',
+                     '--database',
+                     "postgres"
+                 ],
+                 cmd="/test_path/pg_dump"
+             ),
+             extected_msg="Backing up the server"
+                          " 'test_backup_server (localhost:5444)'...",
+             expetced_details_cmd='/test_path/pg_dump --file '
+                                  '"backup_file" --host "localhost" '
+                                  '--port "5444" --username "postgres" '
+                                  '--no-password --database "postgres"'
+
+         )),
+        ('When Backup global',
+         dict(
+             class_params=dict(
+                 type=BACKUP.GLOBALS,
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 args=[
+                     '--file',
+                     'backup_file',
+                     '--host',
+                     'localhost',
+                     '--port',
+                     '5444',
+                     '--username',
+                     'postgres',
+                     '--no-password',
+                     '--database',
+                     'postgres'
+                 ],
+                 cmd="/test_path/pg_dump"
+             ),
+             extected_msg="Backing up the global objects on the server "
+                          "'test_backup_server (localhost:5444)'...",
+             expetced_details_cmd='/test_path/pg_dump --file "backup_file" '
+                                  '--host "localhost"'
+                                  ' --port "5444" --username "postgres" '
+                                  '--no-password --database "postgres"'
+
+         )),
+        ('When backup object',
+         dict(
+             class_params=dict(
+                 type=BACKUP.OBJECT,
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_backup',
+                 args=[
+                     '--file',
+                     'backup_file',
+                     '--host',
+                     'localhost',
+                     '--port',
+                     '5444',
+                     '--username',
+                     'postgres',
+                     '--no-password',
+                     '--database',
+                     'postgres'
+                 ],
+                 cmd="/test_path/pg_dump"
+             ),
+             extected_msg="Backing up an object on the server "
+                          "'test_backup_server (localhost:5444)'"
+                          " from database 'postgres'...",
+             expetced_details_cmd='/test_path/pg_dump --file "backup_file" '
+                                  '--host "localhost" '
+                                  '--port "5444" --username "postgres" '
+                                  '--no-password --database "postgres"'
+
+         ))
+    ]
+
+    @patch('pgadmin.tools.backup.Server')
+    @patch('pgadmin.tools.backup.current_user')
+    def runTest(self, current_user_mock, server_mock):
+        current_user_mock = 1
+
+        class TestMockServer():
+            def __init__(self, name, host, port):
+                self.name = name
+                self.host = host
+                self.port = port
+        mock_obj = TestMockServer(self.class_params['name'],
+                                  self.class_params['host'],
+                                  self.class_params['port'])
+        mock_result = server_mock.query.filter_by.return_value
+        mock_result.first.return_value = mock_obj
+
+        backup_obj = BackupMessage(
+            self.class_params['type'],
+            self.class_params['sid'],
+            self.class_params['bfile'],
+            *self.class_params['args'],
+            **{'database': self.class_params['database']}
+        )
+
+        # Check the expected message returned
+        assert backup_obj.message == self.extected_msg
+
+        # Check the command
+        obj_details = backup_obj.details(self.class_params['cmd'],
+                                         self.class_params['args'])
+        self.assertIn(self.expetced_details_cmd, obj_details)
diff --git a/web/pgadmin/tools/backup/tests/test_backup_utils.py b/web/pgadmin/tools/backup/tests/test_backup_utils.py
new file mode 100644
index 0000000..3c0c98c
--- /dev/null
+++ b/web/pgadmin/tools/backup/tests/test_backup_utils.py
@@ -0,0 +1,111 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+import time
+import random
+import simplejson as json
+
+
+def create_backup_job(tester, url, params):
+    # Create the backup job
+    response = tester.post(url,
+                           data=json.dumps(params),
+                           content_type='html/json')
+    assert response.status_code == 200
+    response_data = json.loads(response.data.decode('utf-8'))
+    job_id = response_data['data']['job_id']
+    return job_id
+
+
+def run_backup_job(tester, job_id, expected_params, assertIn, assertNotIn):
+    cnt = 0
+    while 1:
+        if cnt > 1:
+            break
+        # Check the process list
+        response1 = tester.get('/misc/bgprocess/?_='.format(
+            random.randint(1, 9999999)))
+        assert response1.status_code == 200
+        process_list = json.loads(response1.data.decode('utf-8'))
+
+        if len(process_list) > 0 and 'execution_time' in process_list[0]:
+            break
+        time.sleep(0.5)
+        cnt += 1
+
+    assert 'execution_time' in process_list[0]
+    assert 'stime' in process_list[0]
+    assert 'exit_code' in process_list[0]
+    assert process_list[0]['exit_code'] in expected_params[
+        'expected_exit_code'
+    ]
+
+    if expected_params['expected_cmd_opts']:
+        for opt in expected_params['expected_cmd_opts']:
+            assertIn(opt, process_list[0]['details'])
+    if expected_params['not_expected_cmd_opts']:
+        for opt in expected_params['not_expected_cmd_opts']:
+            assertNotIn(opt, process_list[0]['details'])
+
+    # Check the process details
+    p_details = tester.get('/misc/bgprocess/{0}?_='.format(
+        job_id, random.randint(1, 9999999))
+    )
+    assert p_details.status_code == 200
+    p_details_data = json.loads(p_details.data.decode('utf-8'))
+
+    p_details = tester.get('/misc/bgprocess/{0}/{1}/{2}/?_='.format(
+        job_id, 0, 0, random.randint(1, 9999999))
+    )
+    assert p_details.status_code == 200
+    p_details_data = json.loads(p_details.data.decode('utf-8'))
+
+    cnt = 0
+    # Retrieve the backup job process logs
+    while 1:
+        out, err, status = get_params(p_details_data)
+        if status or cnt >= 10:
+            break
+
+        p_details = tester.get(
+            '/misc/bgprocess/{0}/{1}/{2}/?_={3}'.format(
+                job_id, out, err, random.randint(1, 9999999))
+        )
+        assert p_details.status_code == 200
+        p_details_data = json.loads(p_details.data.decode('utf-8'))
+
+        cnt += 1
+        time.sleep(1)
+
+    # Check the job is complete.
+    backup_ack = tester.put('/misc/bgprocess/{0}'.format(job_id))
+    assert backup_ack.status_code == 200
+    backup_ack_res = json.loads(backup_ack.data.decode('utf-8'))
+
+    assert backup_ack_res['success'] == 1
+
+
+def get_params(data):
+    out = 0
+    out_done = False
+    err = 0
+    err_done = False
+    if 'out' in data:
+        out = data['out'] and data['out']['pos']
+
+        if 'done' in data['out']:
+            out_done = data['out']['done']
+
+    if 'err' in data:
+        err = data['err'] and data['err']['pos']
+
+        if 'done' in data['err']:
+            err_done = data['err']['done']
+
+    return out, err, (out_done and err_done)
diff --git a/web/pgadmin/tools/backup/tests/test_batch_process.py b/web/pgadmin/tools/backup/tests/test_batch_process.py
new file mode 100644
index 0000000..8cba9be
--- /dev/null
+++ b/web/pgadmin/tools/backup/tests/test_batch_process.py
@@ -0,0 +1,219 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import sys
+import simplejson as json
+
+from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
+from pgadmin.tools.backup import BackupMessage, BACKUP
+from pgadmin.utils.route import BaseTestGenerator
+from pickle import dumps, loads
+
+if sys.version_info < (3, 3):
+    from mock import patch
+else:
+    from unittest.mock import patch
+
+
+class BatchProcessTest(BaseTestGenerator):
+    """Test the BatchProcess class"""
+    scenarios = [
+        ('When backup server',
+         dict(
+             class_params=dict(
+                 type=BACKUP.SERVER,
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 username='postgres',
+                 bfile='test_backup',
+                 args=[
+                     '--file',
+                     "backup_file",
+                     '--host',
+                     "localhost",
+                     '--port',
+                     "5444",
+                     '--username',
+                     "postgres",
+                     '--no-password',
+                     '--database',
+                     "postgres"
+                 ],
+                 cmd='backup_server'
+             )
+         )),
+        ('When backup globals',
+         dict(
+             class_params=dict(
+                 type=BACKUP.GLOBALS,
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 username='postgres',
+                 bfile='test_backup',
+                 args=[
+                     '--file',
+                     "backup_file",
+                     '--host',
+                     "localhost",
+                     '--port',
+                     "5444",
+                     '--username',
+                     "postgres",
+                     '--no-password',
+                     '--database',
+                     "postgres"
+                 ],
+                 cmd='backup'
+             )
+         )),
+        ('When backup object',
+         dict(
+             class_params=dict(
+                 type=BACKUP.OBJECT,
+                 sid=1,
+                 name='test_backup_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 username='postgres',
+                 bfile='test_backup',
+                 args=[
+                     '--file',
+                     "backup_file",
+                     '--host',
+                     "localhost",
+                     '--port',
+                     "5444",
+                     '--username',
+                     "postgres",
+                     '--no-password',
+                     '--database',
+                     "postgres"
+                 ],
+                 cmd='backup'
+             )
+         ))
+    ]
+
+    @patch('pgadmin.misc.bgprocess.processes.Popen')
+    @patch('pgadmin.misc.bgprocess.processes.current_app')
+    @patch('pgadmin.misc.bgprocess.processes.db')
+    @patch('pgadmin.tools.backup.Server')
+    @patch('pgadmin.tools.backup.current_user')
+    @patch('pgadmin.misc.bgprocess.processes.current_user')
+    def runTest(self, current_user_mock, current_user, server_mock, db_mock,
+                current_app_mock, popen_mock):
+        current_user.id = 1
+        current_user_mock.id = 1
+        current_app_mock.PGADMIN_RUNTIME = False
+
+        class TestMockServer():
+            def __init__(self, name, host, port):
+                self.name = name
+                self.host = host
+                self.port = port
+
+        def db_session_add_mock(j):
+            cmd_obj = loads(j.desc)
+            assert isinstance(cmd_obj, IProcessDesc)
+            self.assertEquals(cmd_obj.backup_type, self.class_params['type'])
+            self.assertEquals(cmd_obj.bfile, self.class_params['bfile'])
+            self.assertEquals(cmd_obj.database, self.class_params['database'])
+            self.assertEquals(cmd_obj.cmd,
+                              ' --file "backup_file" '
+                              '--host "{0}" '
+                              '--port "{1}" '
+                              '--username "{2}" '
+                              '--no-password '
+                              '--database "{3}"'.format(
+                                  self.class_params['host'],
+                                  self.class_params['port'],
+                                  self.class_params['username'],
+                                  self.class_params['database']
+                              ))
+
+        mock_obj = TestMockServer(self.class_params['name'],
+                                  self.class_params['host'],
+                                  self.class_params['port'])
+        mock_result = server_mock.query.filter_by.return_value
+        mock_result.first.return_value = mock_obj
+
+        db_mock.session.add.side_effect = db_session_add_mock
+
+        backup_obj = BackupMessage(
+            self.class_params['type'],
+            self.class_params['sid'],
+            self.class_params['bfile'],
+            *self.class_params['args'],
+            **{'database': self.class_params['database']}
+        )
+
+        p = BatchProcess(
+            desc=backup_obj,
+            cmd=self.class_params['cmd'],
+            args=self.class_params['args']
+        )
+
+        # Check that _create_process has been called
+        assert db_mock.session.add.called
+
+        # Check start method
+        self._check_start(popen_mock, p)
+
+        # Check list method
+        self._check_list(p, backup_obj)
+
+    def _check_start(self, popen_mock, p):
+        cmd_test = self.class_params['cmd']
+
+        class popenMockSideEffect():
+            def __init__(self, cmd, **kwargs):
+                assert cmd_test in cmd
+                assert 'env' in kwargs
+
+            def poll(self):
+                pass
+
+        popen_mock.side_effect = popenMockSideEffect
+        p.start()
+
+        assert popen_mock.called
+
+    @patch('pgadmin.misc.bgprocess.processes.Process')
+    @patch('pgadmin.misc.bgprocess.processes.BatchProcess.'
+           'update_process_info')
+    def _check_list(self, p, backup_obj, update_process_info_mock,
+                    process_mock):
+        class TestMockProcess():
+            def __init__(self, desc, args, cmd):
+                self.pid = 1
+                self.exit_code = 1
+                self.start_time = '2018-04-17 06:18:56.315445 +0000'
+                self.end_time = None
+                self.desc = dumps(desc)
+                self.arguments = " ".join(args)
+                self.command = cmd
+                self.acknowledge = None
+
+        process_mock.query.filter_by.return_value = [
+            TestMockProcess(backup_obj,
+                            self.class_params['args'],
+                            self.class_params['cmd'])]
+
+        update_process_info_mock.return_value = [True, True]
+
+        ret_value = p.list()
+        self.assertEqual(1, len(ret_value))
+        assert 'details' in ret_value[0]
+        assert 'desc' in ret_value[0]
diff --git a/web/pgadmin/tools/backup/tests/test_create_backup_job.py b/web/pgadmin/tools/backup/tests/test_create_backup_job.py
new file mode 100644
index 0000000..d9f0531
--- /dev/null
+++ b/web/pgadmin/tools/backup/tests/test_create_backup_job.py
@@ -0,0 +1,58 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+import pgadmin.tools.backup.tests.test_backup_utils as backup_utils
+
+
+class BackupJobTest(BaseTestGenerator):
+    """Backup api test cases"""
+    scenarios = [
+        ('When backup the object with the default options',
+         dict(
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 blobs=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres'
+             ),
+             url='/backup/job/{0}/object',
+             expected_params=dict(
+                 expected_cmd_opts=['--verbose', '--format=c', '--blobs'],
+                 not_expected_cmd_opts=[],
+                 expected_exit_code=[0, None]
+             )
+         ))
+    ]
+
+    def setUp(self):
+        if self.server['DEFAULT_BINARY_PATHS'] is None:
+            self.skipTest(
+                "DEFAULT_BINARY_PATHS is not set for the server {0}".format(
+                    self.server['name']
+                )
+            )
+
+    def runTest(self):
+        self.server_id = parent_node_dict["server"][-1]["server_id"]
+        url = self.url.format(self.server_id)
+
+        # Create the backup job
+        job_id = backup_utils.create_backup_job(self.tester, url, self.params)
+        backup_utils.run_backup_job(self.tester,
+                                    job_id,
+                                    self.expected_params,
+                                    self.assertIn,
+                                    self.assertNotIn
+                                    )
diff --git a/web/pgadmin/tools/maintenance/tests/__init__.py b/web/pgadmin/tools/maintenance/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/web/pgadmin/tools/maintenance/tests/test_batch_process_maintenance.py b/web/pgadmin/tools/maintenance/tests/test_batch_process_maintenance.py
new file mode 100644
index 0000000..55c3db8
--- /dev/null
+++ b/web/pgadmin/tools/maintenance/tests/test_batch_process_maintenance.py
@@ -0,0 +1,153 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import sys
+
+from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
+from pgadmin.tools.maintenance import Message
+from pgadmin.utils.route import BaseTestGenerator
+from pickle import dumps, loads
+
+if sys.version_info < (3, 3):
+    from mock import patch
+else:
+    from unittest.mock import patch
+
+
+class BatchProcessTest(BaseTestGenerator):
+    """Test the BatchProcess class"""
+    scenarios = [
+        ('When maintained server',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 host='localhost',
+                 port=5444,
+                 username='postgres',
+                 args=[
+                     '--host',
+                     "localhost",
+                     '--port',
+                     "5444",
+                     '--username',
+                     '--dbname',
+                     "postgres",
+                     '--command',
+                     "VACUUM VERBOSE;\n"
+                 ],
+                 data={
+                     'database': 'postgres',
+                     'op': 'VACUUM',
+                     'vacuum_analyze': False,
+                     'vacuum_freeze': False,
+                     'vacuum_full': False,
+                     'verbose': True
+                 },
+                 cmd="VACUUM VERBOSE;\n"
+             ),
+             expected_msg="Maintenance (Vacuum)",
+             expetced_details_cmd='VACUUM VERBOSE;'
+         ))
+    ]
+
+    @patch('pgadmin.misc.bgprocess.processes.Popen')
+    @patch('pgadmin.misc.bgprocess.processes.current_app')
+    @patch('pgadmin.misc.bgprocess.processes.db')
+    @patch('pgadmin.tools.maintenance.Server')
+    @patch('pgadmin.misc.bgprocess.processes.current_user')
+    def runTest(self, current_user_mock, server_mock, db_mock,
+                current_app_mock, popen_mock):
+        current_user_mock.id = 1
+        current_app_mock.PGADMIN_RUNTIME = False
+
+        class TestMockServer():
+            def __init__(self, name, host, port):
+                self.name = name
+                self.host = host
+                self.port = port
+
+        def db_session_add_mock(j):
+            cmd_obj = loads(j.desc)
+            assert isinstance(cmd_obj, IProcessDesc)
+            self.assertEquals(cmd_obj.query, self.class_params['cmd'])
+            self.assertEquals(cmd_obj.message, self.expected_msg)
+            self.assertEquals(cmd_obj.data, self.class_params['data'])
+
+        mock_obj = TestMockServer(self.class_params['username'],
+                                  self.class_params['host'],
+                                  self.class_params['port'])
+        mock_result = server_mock.query.filter_by.return_value
+        mock_result.first.return_value = mock_obj
+
+        db_mock.session.add.side_effect = db_session_add_mock
+
+        maintenance_obj = Message(
+            self.class_params['sid'],
+            self.class_params['data'],
+            self.class_params['cmd']
+        )
+
+        p = BatchProcess(
+            desc=maintenance_obj,
+            cmd=self.class_params['cmd'],
+            args=self.class_params['args']
+        )
+
+        # Check that _create_process has been called
+        assert db_mock.session.add.called
+
+        # Check start method
+        self._check_start(popen_mock, p)
+
+        # Check list method
+        self._check_list(p, maintenance_obj)
+
+    def _check_start(self, popen_mock, p):
+        cmd_test = self.class_params['cmd']
+
+        class popenMockSideEffect():
+            def __init__(self, cmd, **kwargs):
+                assert cmd_test in cmd
+                assert 'env' in kwargs
+
+            def poll(self):
+                pass
+
+        popen_mock.side_effect = popenMockSideEffect
+        p.start()
+
+        assert popen_mock.called
+
+    @patch('pgadmin.misc.bgprocess.processes.Process')
+    @patch('pgadmin.misc.bgprocess.processes.BatchProcess.'
+           'update_process_info')
+    def _check_list(self, p, maintenance_obj, update_process_info_mock,
+                    process_mock):
+        class TestMockProcess():
+            def __init__(self, desc, args, cmd):
+                self.pid = 1
+                self.exit_code = 1
+                self.start_time = '2018-04-17 06:18:56.315445 +0000'
+                self.end_time = None
+                self.desc = dumps(desc)
+                self.arguments = " ".join(args)
+                self.command = cmd
+                self.acknowledge = None
+
+        process_mock.query.filter_by.return_value = [
+            TestMockProcess(maintenance_obj,
+                            self.class_params['args'],
+                            self.class_params['cmd'])
+        ]
+
+        update_process_info_mock.return_value = [True, True]
+
+        ret_value = p.list()
+        self.assertEqual(1, len(ret_value))
+        assert 'details' in ret_value[0]
+        assert 'desc' in ret_value[0]
diff --git a/web/pgadmin/tools/maintenance/tests/test_create_maintenance_job.py b/web/pgadmin/tools/maintenance/tests/test_create_maintenance_job.py
new file mode 100644
index 0000000..a424920
--- /dev/null
+++ b/web/pgadmin/tools/maintenance/tests/test_create_maintenance_job.py
@@ -0,0 +1,142 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import time
+import random
+import simplejson as json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+from pgadmin.utils import server_utils as server_utils
+from pgadmin.browser.server_groups.servers.databases.tests import utils as \
+    database_utils
+
+
+class MaintenanceJobTest(BaseTestGenerator):
+    """Maintenance api test cases"""
+    scenarios = [
+        ('When maintenance the object with the default options',
+         dict(
+             params=dict(
+                 data={
+                     'database': 'postgres',
+                     'op': 'VACUUM',
+                     'vacuum_analyze': False,
+                     'vacuum_freeze': False,
+                     'vacuum_full': False,
+                     'verbose': True
+                 },
+                 cmd="VACUUM VERBOSE;\n"
+             ),
+             url='/maintenance/job/{0}/{1}',
+             expected_cmd='VACUUM VERBOSE',
+             expected_exit_code=[0, None]
+         ))
+    ]
+
+    def setUp(self):
+        if self.server['DEFAULT_BINARY_PATHS'] is None:
+            self.skipTest(
+                "DEFAULT_BINARY_PATHS is not set for the server {0}".format(
+                    self.server['name']
+                )
+            )
+
+    def runTest(self):
+        self.db_name = ''
+        self.server_id = parent_node_dict["database"][-1]["server_id"]
+        self.db_id = parent_node_dict["database"][-1]["db_id"]
+        url = self.url.format(self.server_id, self.db_id)
+
+        utils.set_preference(self.server['DEFAULT_BINARY_PATHS'])
+
+        # Create the backup job
+        response = self.tester.post(url,
+                                    data=json.dumps(self.params['data']),
+                                    content_type='html/json')
+        self.assertEquals(response.status_code, 200)
+        response_data = json.loads(response.data.decode('utf-8'))
+        job_id = response_data['data']['job_id']
+
+        cnt = 0
+        while 1:
+            if cnt > 1:
+                break
+            # Check the process list
+            response1 = self.tester.get('/misc/bgprocess/?_='.format(
+                random.randint(1, 9999999)))
+            self.assertEquals(response1.status_code, 200)
+            process_list = json.loads(response1.data.decode('utf-8'))
+
+            if len(process_list) > 0 and 'execution_time' in process_list[0]:
+                break
+            time.sleep(0.5)
+            cnt += 1
+
+        assert 'execution_time' in process_list[0]
+        assert 'stime' in process_list[0]
+        assert 'exit_code' in process_list[0]
+        assert process_list[0]['exit_code'] in self.expected_exit_code
+
+        self.assertIn(self.expected_cmd, process_list[0]['details'])
+
+        # Check the process details
+        p_details = self.tester.get('/misc/bgprocess/{0}?_='.format(
+            job_id, random.randint(1, 9999999))
+        )
+        self.assertEquals(p_details.status_code, 200)
+        p_details_data = json.loads(p_details.data.decode('utf-8'))
+
+        p_details = self.tester.get('/misc/bgprocess/{0}/{1}/{2}/?_='.format(
+            job_id, 0, 0, random.randint(1, 9999999))
+        )
+        self.assertEquals(p_details.status_code, 200)
+        p_details_data = json.loads(p_details.data.decode('utf-8'))
+
+        # Retrieve the backup job process logs
+        while 1:
+            out, err, status = MaintenanceJobTest.get_params(p_details_data)
+            if status:
+                break
+
+            p_details = self.tester.get(
+                '/misc/bgprocess/{0}/{1}/{2}/?_={3}'.format(
+                    job_id, out, err, random.randint(1, 9999999))
+            )
+            self.assertEquals(p_details.status_code, 200)
+            p_details_data = json.loads(p_details.data.decode('utf-8'))
+
+            time.sleep(1)
+
+        # Check the job is complete.
+        backup_ack = self.tester.put('/misc/bgprocess/{0}'.format(job_id))
+        self.assertEquals(backup_ack.status_code, 200)
+        backup_ack_res = json.loads(backup_ack.data.decode('utf-8'))
+
+        self.assertEquals(backup_ack_res['success'], 1)
+
+    @staticmethod
+    def get_params(data):
+        out = 0
+        out_done = False
+        err = 0
+        err_done = False
+        if 'out' in data:
+            out = data['out'] and data['out']['pos']
+
+            if 'done' in data['out']:
+                out_done = data['out']['done']
+
+        if 'err' in data:
+            err = data['err'] and data['err']['pos']
+
+            if 'done' in data['err']:
+                err_done = data['err']['done']
+
+        return out, err, (out_done and err_done)
diff --git a/web/pgadmin/tools/maintenance/tests/test_maintenance_create_job_unit_test.py b/web/pgadmin/tools/maintenance/tests/test_maintenance_create_job_unit_test.py
new file mode 100644
index 0000000..6cf0465
--- /dev/null
+++ b/web/pgadmin/tools/maintenance/tests/test_maintenance_create_job_unit_test.py
@@ -0,0 +1,195 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+
+import sys
+import simplejson as json
+
+
+from pgadmin.misc.bgprocess.processes import BatchProcess
+from pgadmin.tools.maintenance import Message
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+from pgadmin.utils import server_utils as server_utils
+from pgadmin.browser.server_groups.servers.databases.tests import utils as \
+    database_utils
+
+
+if sys.version_info < (3, 3):
+    from mock import patch, MagicMock
+else:
+    from unittest.mock import patch, MagicMock
+
+
+class MaintenanceCreateJobTest(BaseTestGenerator):
+    """Test the BackupCreateJob class"""
+    scenarios = [
+        ('When maintenance object with default options',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_maintenance_server',
+                 port=5444,
+                 host='localhost',
+                 username='postgres'
+             ),
+             params=dict(
+                 database='postgres',
+                 op='VACUUM',
+                 vacuum_analyze=False,
+                 vacuum_freeze=False,
+                 vacuum_full=False,
+                 verbose=True
+             ),
+             url='/maintenance/job/{0}/{1}',
+             expected_cmd_opts=['VACUUM VERBOSE;\n'],
+         )),
+        ('When maintenance object with VACUUM FULL',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_maintenance_server',
+                 port=5444,
+                 host='localhost',
+                 username='postgres'
+             ),
+             params=dict(
+                 database='postgres',
+                 op='VACUUM',
+                 vacuum_analyze=False,
+                 vacuum_freeze=False,
+                 vacuum_full=True,
+                 verbose=True
+             ),
+             url='/maintenance/job/{0}/{1}',
+             expected_cmd_opts=['VACUUM FULL VERBOSE;\n'],
+         )),
+        ('When maintenance object with the ANALYZE',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_maintenance_server',
+                 port=5444,
+                 host='localhost',
+                 username='postgres'
+             ),
+             params=dict(
+                 database='postgres',
+                 op='ANALYZE',
+                 vacuum_analyze=True,
+                 vacuum_freeze=False,
+                 vacuum_full=False,
+                 verbose=True
+             ),
+             url='/maintenance/job/{0}/{1}',
+             expected_cmd_opts=['ANALYZE VERBOSE;\n'],
+         )),
+        ('When maintenance the object with the REINDEX',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_maintenance_server',
+                 port=5444,
+                 host='localhost',
+                 username='postgres'
+             ),
+             params=dict(
+                 database='postgres',
+                 op='REINDEX',
+                 vacuum_analyze=False,
+                 vacuum_freeze=False,
+                 vacuum_full=False,
+                 verbose=False
+             ),
+             url='/maintenance/job/{0}/{1}',
+             expected_cmd_opts=['REINDEX DATABASE postgres;\n'],
+         )),
+        ('When maintenance the object with the CLUSTER',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_maintenance_server',
+                 port=5444,
+                 host='localhost',
+                 username='postgres'
+             ),
+             params=dict(
+                 database='postgres',
+                 op='CLUSTER',
+                 vacuum_analyze=False,
+                 vacuum_freeze=False,
+                 vacuum_full=False,
+                 verbose=False
+             ),
+             url='/maintenance/job/{0}/{1}',
+             expected_cmd_opts=['CLUSTER;\n'],
+         ))
+    ]
+
+    def setUp(self):
+        if self.server['DEFAULT_BINARY_PATHS'] is None:
+            self.skipTest(
+                "DEFAULT_BINARY_PATHS is not set for the server {0}".format(
+                    self.server['name']
+                )
+            )
+
+    @patch('pgadmin.tools.maintenance.Server')
+    @patch('pgadmin.tools.maintenance.Message')
+    @patch('pgadmin.tools.maintenance.BatchProcess')
+    def runTest(self, batch_process_mock, message_mock, server_mock):
+        self.server_id = parent_node_dict["database"][-1]["server_id"]
+        self.db_id = parent_node_dict["database"][-1]["db_id"]
+        url = self.url.format(self.server_id, self.db_id)
+
+        class TestMockServer():
+            def __init__(self, host, port, id, username):
+                self.host = host
+                self.port = port
+                self.id = id
+                self.username = username
+
+        mock_obj = TestMockServer(self.class_params['host'],
+                                  self.class_params['port'],
+                                  self.server_id,
+                                  self.class_params['username']
+                                  )
+        mock_result = server_mock.query.filter_by.return_value
+        mock_result.first.return_value = mock_obj
+
+        batch_process_mock.set_env_variables = MagicMock(
+            return_value=True
+        )
+        batch_process_mock.start = MagicMock(
+            return_value=True
+        )
+
+        server_response = server_utils.connect_server(self, self.server_id)
+        if server_response["info"] == "Server connected.":
+            db_owner = server_response['data']['user']['name']
+            self.data = database_utils.get_db_data(db_owner)
+            self.db_name = self.data['name']
+
+        # Create the backup job
+        response = self.tester.post(url,
+                                    data=json.dumps(self.params),
+                                    content_type='html/json')
+        self.assertEquals(response.status_code, 200)
+        response_data = json.loads(response.data.decode('utf-8'))
+        job_id = response_data['data']['job_id']
+
+        assert message_mock.called
+        assert batch_process_mock.called
+
+        print(batch_process_mock.call_args_list[0][1]['args'])
+        if self.expected_cmd_opts:
+            for opt in self.expected_cmd_opts:
+                self.assertIn(opt,
+                              batch_process_mock.call_args_list[0][1]['args'])
diff --git a/web/pgadmin/tools/maintenance/tests/test_maintenance_message.py b/web/pgadmin/tools/maintenance/tests/test_maintenance_message.py
new file mode 100644
index 0000000..4cb89ed
--- /dev/null
+++ b/web/pgadmin/tools/maintenance/tests/test_maintenance_message.py
@@ -0,0 +1,124 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+from flask import Response
+import simplejson as json
+
+from pgadmin.tools.maintenance import Message
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class MaintenanceMessageTest(BaseTestGenerator):
+    """Test the Maintenance Message class"""
+    scenarios = [
+        ('When maintained the server',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 data={
+                     'database': 'postgres',
+                     'op': 'VACUUM',
+                     'vacuum_analyze': False,
+                     'vacuum_freeze': False,
+                     'vacuum_full': False,
+                     'verbose': True
+                 },
+                 cmd="VACUUM VERBOSE;\n"
+             ),
+             extected_msg="Maintenance (Vacuum)",
+             expetced_details_cmd='VACUUM VERBOSE;'
+
+         )),
+        ('When maintained the server with FULL VERBOSE options',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 data={
+                     'database': 'postgres',
+                     'op': 'VACUUM',
+                     'vacuum_analyze': False,
+                     'vacuum_freeze': False,
+                     'vacuum_full': True,
+                     'verbose': True
+                 },
+                 cmd="VACUUM FULL VERBOSE;\n"
+             ),
+             extected_msg="Maintenance (Vacuum)",
+             expetced_details_cmd='VACUUM FULL VERBOSE;'
+
+         )),
+        ('When maintained the server with ANALYZE',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 data={
+                     'database': 'postgres',
+                     'op': 'ANALYZE',
+                     'vacuum_analyze': False,
+                     'vacuum_freeze': False,
+                     'vacuum_full': False,
+                     'verbose': True
+                 },
+                 cmd="ANALYZE VERBOSE;\n"
+             ),
+             extected_msg="Maintenance (Analyze)",
+             expetced_details_cmd='ANALYZE VERBOSE;'
+
+         )),
+        ('When maintained the server with REINDEX',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 data={
+                     'database': 'postgres',
+                     'op': 'REINDEX',
+                     'vacuum_analyze': False,
+                     'vacuum_freeze': False,
+                     'vacuum_full': False,
+                     'verbose': False
+                 },
+                 cmd="REINDEX;\n"
+             ),
+             extected_msg="Maintenance (Reindex)",
+             expetced_details_cmd='REINDEX;'
+
+         )),
+        ('When maintained the server with CLUSTER',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 data={
+                     'database': 'postgres',
+                     'op': 'CLUSTER',
+                     'vacuum_analyze': False,
+                     'vacuum_freeze': False,
+                     'vacuum_full': False,
+                     'verbose': True
+                 },
+                 cmd="CLUSTER VERBOSE;\n"
+             ),
+             extected_msg="Maintenance (Cluster)",
+             expetced_details_cmd='CLUSTER VERBOSE;'
+
+         )),
+    ]
+
+    def runTest(self):
+        maintenance_obj = Message(
+            self.class_params['sid'],
+            self.class_params['data'],
+            self.class_params['cmd']
+        )
+
+        # Check the expected message returned
+        assert maintenance_obj.message == self.extected_msg
+
+        # Check the command
+        obj_details = maintenance_obj.details(self.class_params['cmd'], None)
+        self.assertIn(self.expetced_details_cmd, obj_details)
diff --git a/web/pgadmin/tools/restore/__init__.py b/web/pgadmin/tools/restore/__init__.py
index f6f92b9..460d01f 100644
--- a/web/pgadmin/tools/restore/__init__.py
+++ b/web/pgadmin/tools/restore/__init__.py
@@ -192,6 +192,7 @@ def create_restore_job(sid):
 
     if _file is None:
         return make_json_response(
+            status=410,
             success=0,
             errormsg=_("File could not be found.")
         )
diff --git a/web/pgadmin/tools/restore/tests/__init__.py b/web/pgadmin/tools/restore/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/web/pgadmin/tools/restore/tests/test_batch_process.py b/web/pgadmin/tools/restore/tests/test_batch_process.py
new file mode 100644
index 0000000..3c674e1
--- /dev/null
+++ b/web/pgadmin/tools/restore/tests/test_batch_process.py
@@ -0,0 +1,161 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import sys
+
+from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
+from pgadmin.tools.restore import RestoreMessage
+from pgadmin.utils.route import BaseTestGenerator
+from pickle import dumps, loads
+
+if sys.version_info < (3, 3):
+    from mock import patch
+else:
+    from unittest.mock import patch
+
+
+class BatchProcessTest(BaseTestGenerator):
+    """Test the BatchProcess class"""
+    scenarios = [
+        ('When restore server',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_restore_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 username='postgres',
+                 bfile='test_restore',
+                 args=[
+                     '--file',
+                     "restore_file",
+                     '--host',
+                     "localhost",
+                     '--port',
+                     "5444",
+                     '--username',
+                     "postgres",
+                     '--no-password',
+                     '--database',
+                     "postgres"
+                 ],
+                 cmd='restore_server'
+             )
+         ))
+    ]
+
+    @patch('pgadmin.misc.bgprocess.processes.Popen')
+    @patch('pgadmin.misc.bgprocess.processes.current_app')
+    @patch('pgadmin.misc.bgprocess.processes.db')
+    @patch('pgadmin.tools.restore.Server')
+    @patch('pgadmin.tools.restore.current_user')
+    @patch('pgadmin.misc.bgprocess.processes.current_user')
+    def runTest(self, current_user_mock, current_user, server_mock, db_mock,
+                current_app_mock, popen_mock):
+        current_user.id = 1
+        current_user_mock.id = 1
+        current_app_mock.PGADMIN_RUNTIME = False
+
+        class TestMockServer():
+            def __init__(self, name, host, port):
+                self.name = name
+                self.host = host
+                self.port = port
+
+        def db_session_add_mock(j):
+            cmd_obj = loads(j.desc)
+            assert isinstance(cmd_obj, IProcessDesc)
+            print(cmd_obj)
+            self.assertEquals(cmd_obj.bfile, self.class_params['bfile'])
+            self.assertEquals(cmd_obj.cmd,
+                              ' --file "restore_file" '
+                              '--host "{0}" '
+                              '--port "{1}" '
+                              '--username "{2}" '
+                              '--no-password '
+                              '--database "{3}"'.format(
+                                  self.class_params['host'],
+                                  self.class_params['port'],
+                                  self.class_params['username'],
+                                  self.class_params['database']
+                              ))
+
+        mock_obj = TestMockServer(self.class_params['name'],
+                                  self.class_params['host'],
+                                  self.class_params['port'])
+        mock_result = server_mock.query.filter_by.return_value
+        mock_result.first.return_value = mock_obj
+
+        db_mock.session.add.side_effect = db_session_add_mock
+
+        restore_obj = RestoreMessage(
+            self.class_params['sid'],
+            self.class_params['bfile'],
+            *self.class_params['args']
+        )
+
+        p = BatchProcess(
+            desc=restore_obj,
+            cmd=self.class_params['cmd'],
+            args=self.class_params['args']
+        )
+
+        # Check that _create_process has been called
+        assert db_mock.session.add.called
+
+        # Check start method
+        self._check_start(popen_mock, p)
+
+        # Check list method
+        self._check_list(p, restore_obj)
+
+    def _check_start(self, popen_mock, p):
+        cmd_test = self.class_params['cmd']
+
+        class popenMockSideEffect():
+            def __init__(self, cmd, **kwargs):
+                assert cmd_test in cmd
+                assert 'env' in kwargs
+
+            def poll(self):
+                pass
+
+        popen_mock.side_effect = popenMockSideEffect
+        p.start()
+
+        assert popen_mock.called
+
+    @patch('pgadmin.misc.bgprocess.processes.Process')
+    @patch('pgadmin.misc.bgprocess.processes.BatchProcess.'
+           'update_process_info')
+    def _check_list(self, p, restore_obj, update_process_info_mock,
+                    process_mock):
+        class TestMockProcess():
+            def __init__(self, desc, args, cmd):
+                self.pid = 1
+                self.exit_code = 1
+                self.start_time = '2018-04-17 06:18:56.315445 +0000'
+                self.end_time = None
+                self.desc = dumps(desc)
+                self.arguments = " ".join(args)
+                self.command = cmd
+                self.acknowledge = None
+
+        process_mock.query.filter_by.return_value = [
+            TestMockProcess(restore_obj,
+                            self.class_params['args'],
+                            self.class_params['cmd'])
+        ]
+
+        update_process_info_mock.return_value = [True, True]
+
+        ret_value = p.list()
+        self.assertEqual(1, len(ret_value))
+        assert 'details' in ret_value[0]
+        assert 'desc' in ret_value[0]
diff --git a/web/pgadmin/tools/restore/tests/test_create_restore_job.py b/web/pgadmin/tools/restore/tests/test_create_restore_job.py
new file mode 100644
index 0000000..64b12b6
--- /dev/null
+++ b/web/pgadmin/tools/restore/tests/test_create_restore_job.py
@@ -0,0 +1,196 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import sys
+import time
+import random
+
+import simplejson as json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+from pgadmin.utils import server_utils as server_utils
+import pgadmin.tools.backup.tests.test_backup_utils as backup_utils
+
+
+if sys.version_info < (3, 3):
+    from mock import patch, MagicMock
+else:
+    from unittest.mock import patch, MagicMock
+
+
+class RestoreJobTest(BaseTestGenerator):
+    """Backup api test cases"""
+    scenarios = [
+        ('When restore the object with the default options',
+         dict(
+             params=dict(
+                 file='test_restore_file',
+                 format='custom',
+                 custom=False,
+                 verbose=True,
+                 blobs=True,
+                 schemas=[],
+                 tables=[],
+                 database='test_restore_database'
+             ),
+             url='/restore/job/{0}',
+             expected_cmd_opts=['--verbose'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None],
+             backup_options=dict(
+                 params=dict(
+                     file='test_restore_file',
+                     format='custom',
+                     verbose=True,
+                     blobs=True,
+                     schemas=[],
+                     tables=[],
+                     database='test_restore_database'
+                 ),
+                 url='/backup/job/{0}/object',
+                 expected_params=dict(
+                     expected_cmd_opts=['--verbose', '--format=c', '--blobs'],
+                     not_expected_cmd_opts=[],
+                     expected_exit_code=[0, None]
+                 )
+
+             )
+         ))
+    ]
+
+    def setUp(self):
+        if self.server['DEFAULT_BINARY_PATHS'] is None:
+            self.skipTest(
+                "DEFAULT_BINARY_PATHS is not set for the server {0}".format(
+                    self.server['name']
+                )
+            )
+
+    def create_backup(self):
+        url = self.backup_options['url'].format(self.server_id)
+        job_id = backup_utils.create_backup_job(self.tester, url,
+                                                self.backup_options['params'])
+        backup_utils.run_backup_job(self.tester, job_id,
+                                    self.backup_options['expected_params'],
+                                    self.assertIn, self.assertNotIn)
+
+    def runTest(self):
+        self.db_name = ''
+        self.server_id = parent_node_dict["server"][-1]["server_id"]
+        server_response = server_utils.connect_server(self, self.server_id)
+        db_id = utils.create_database(self.server, self.params['database'])
+
+        self.create_backup()
+        url = self.url.format(self.server_id)
+
+        # Create the restore job
+        response = self.tester.post(url,
+                                    data=json.dumps(self.params),
+                                    content_type='html/json')
+        self.assertEquals(response.status_code, 200)
+        response_data = json.loads(response.data.decode('utf-8'))
+        job_id = response_data['data']['job_id']
+
+        cnt = 0
+        while 1:
+            if cnt > 1:
+                break
+            # Check the process list
+            response1 = self.tester.get('/misc/bgprocess/?_='.format(
+                random.randint(1, 9999999)))
+            self.assertEquals(response1.status_code, 200)
+            process_list = json.loads(response1.data.decode('utf-8'))
+
+            if len(process_list) > 0 and 'execution_time' in process_list[0]:
+                break
+            time.sleep(0.5)
+            cnt += 1
+
+        print(process_list[0])
+
+        assert 'execution_time' in process_list[0]
+        assert 'stime' in process_list[0]
+        assert 'exit_code' in process_list[0]
+        assert process_list[0]['exit_code'] in self.expected_exit_code
+
+        if self.expected_cmd_opts:
+            for opt in self.expected_cmd_opts:
+                self.assertIn(opt, process_list[0]['details'])
+        if self.not_expected_cmd_opts:
+            for opt in self.not_expected_cmd_opts:
+                self.assertNotIn(opt, process_list[0]['details'])
+
+        # Check the process details
+        p_details = self.tester.get('/misc/bgprocess/{0}?_='.format(
+            job_id, random.randint(1, 9999999))
+        )
+        self.assertEquals(p_details.status_code, 200)
+        p_details_data = json.loads(p_details.data.decode('utf-8'))
+
+        p_details = self.tester.get('/misc/bgprocess/{0}/{1}/{2}/?_='.format(
+            job_id, 0, 0, random.randint(1, 9999999))
+        )
+        self.assertEquals(p_details.status_code, 200)
+        p_details_data = json.loads(p_details.data.decode('utf-8'))
+
+        # Retrieve the restore job process logs
+        cnt = 0
+        while 1:
+            out, err, status = RestoreJobTest.get_params(p_details_data)
+            if status or cnt >= 10:
+                break
+
+            p_details = self.tester.get(
+                '/misc/bgprocess/{0}/{1}/{2}/?_={3}'.format(
+                    job_id, out, err, random.randint(1, 9999999))
+            )
+            self.assertEquals(p_details.status_code, 200)
+            p_details_data = json.loads(p_details.data.decode('utf-8'))
+
+            cnt += 1
+            time.sleep(1)
+
+        # Check the job is complete.
+        restore_ack = self.tester.put('/misc/bgprocess/{0}'.format(job_id))
+        self.assertEquals(restore_ack.status_code, 200)
+        restore_ack_res = json.loads(restore_ack.data.decode('utf-8'))
+
+        self.assertEquals(restore_ack_res['success'], 1)
+
+    @staticmethod
+    def get_params(data):
+        out = 0
+        out_done = False
+        err = 0
+        err_done = False
+        if 'out' in data:
+            out = data['out'] and data['out']['pos']
+
+            if 'done' in data['out']:
+                out_done = data['out']['done']
+
+        if 'err' in data:
+            err = data['err'] and data['err']['pos']
+
+            if 'done' in data['err']:
+                err_done = data['err']['done']
+
+        return out, err, (out_done and err_done)
+
+    def after(self):
+        connection = utils.get_db_connection(
+            self.server['db'],
+            self.server['username'],
+            self.server['db_password'],
+            self.server['host'],
+            self.server['port'],
+            self.server['sslmode']
+        )
+        utils.drop_database(connection, self.params['database'])
diff --git a/web/pgadmin/tools/restore/tests/test_restore_create_job_unit_test.py b/web/pgadmin/tools/restore/tests/test_restore_create_job_unit_test.py
new file mode 100644
index 0000000..0cf315f
--- /dev/null
+++ b/web/pgadmin/tools/restore/tests/test_restore_create_job_unit_test.py
@@ -0,0 +1,313 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+import sys
+import simplejson as json
+
+from pgadmin.tools.restore import RestoreMessage
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+from pgadmin.utils import server_utils as server_utils
+from pgadmin.browser.server_groups.servers.databases.tests import utils as \
+    database_utils
+
+if sys.version_info < (3, 3):
+    from mock import patch, MagicMock
+else:
+    from unittest.mock import patch, MagicMock
+
+
+class RestoreCreateJobTest(BaseTestGenerator):
+    """Test the RestoreCreateJob class"""
+    scenarios = [
+        ('When restore object with default options',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_restore_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_restore',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_restore_file',
+                 format='custom',
+                 custom=False,
+                 verbose=True,
+                 blobs=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres'
+             ),
+             url='/restore/job/{0}',
+             expected_cmd_opts=['--verbose'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When restore object with the sections options',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_restore_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_restore',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_restore_file',
+                 format='custom',
+                 no_of_jobs='2',
+                 custom=False,
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 data=True,
+                 pre_data=True,
+                 post_data=True,
+                 only_data=True,
+                 only_schema=True
+             ),
+             url='/restore/job/{0}',
+             # Please include sections data here, right now this is a bug
+             expected_cmd_opts=['--verbose', '--jobs', '2'],
+             not_expected_cmd_opts=[],
+             # Below options should be enabled once we fix the issue #3368
+             # not_expected_cmd_opts=['--data-only', '--schema-only'],
+             expected_exit_code=[0, None],
+         )),
+        ('When restore the object with Type of objects',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_restore_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_restore',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_restore_file',
+                 format='custom',
+                 no_of_jobs='2',
+                 custom=False,
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 only_data=True,
+                 only_schema=True,
+                 dns_owner=True
+             ),
+             url='/restore/job/{0}',
+             expected_cmd_opts=['--verbose', '--data-only'],
+             not_expected_cmd_opts=[],
+             # Below options should be enabled once we fix the issue #3368
+             # not_expected_cmd_opts=['--schema-only', '--no-owner'],
+             expected_exit_code=[0, None],
+         )),
+        ('When restore object with option - Do not save',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_restore_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_restore',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_restore_file',
+                 format='custom',
+                 verbose=True,
+                 custom=False,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 dns_owner=True,
+                 dns_privilege=True,
+                 dns_tablespace=True,
+                 only_data=False
+             ),
+             url='/restore/job/{0}',
+             # Add '--no-privileges' to the expected_cmd once #3363 fixed
+             expected_cmd_opts=['--no-owner',
+                                '--no-tablespaces'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When restore object with option - Queries',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_restore_file',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_restore',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 clean=True,
+                 include_create_database=True,
+                 single_transaction=True,
+             ),
+             url='/restore/job/{0}',
+             expected_cmd_opts=['--create', '--clean',
+                                '--single-transaction'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When restore object with option - Disbale',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_restore_file',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_restore',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 disable_trigger=True,
+                 no_data_fail_table=True,
+                 only_schema=False
+             ),
+             url='/restore/job/{0}',
+             # Add '--no-data-for-failed-tables' into
+             # expected_cmd_opts once #3363 fixed
+             expected_cmd_opts=['--disable-triggers'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+        ('When restore object with option - Miscellaneous',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_restore_file',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_restore',
+                 username='postgres'
+             ),
+             params=dict(
+                 file='test_backup_file',
+                 format='custom',
+                 verbose=True,
+                 schemas=[],
+                 tables=[],
+                 database='postgres',
+                 use_set_session_auth=True,
+                 exit_on_error=True,
+             ),
+             url='/restore/job/{0}',
+             # Add '--use_set_session_auth' into
+             # expected_cmd_opts once #3363 fixed
+             expected_cmd_opts=['--exit-on-error'],
+             not_expected_cmd_opts=[],
+             expected_exit_code=[0, None]
+         )),
+    ]
+
+    def setUp(self):
+        if self.server['DEFAULT_BINARY_PATHS'] is None:
+            self.skipTest(
+                "DEFAULT_BINARY_PATHS is not set for the server {0}".format(
+                    self.server['name']
+                )
+            )
+
+    @patch('pgadmin.tools.restore.Server')
+    @patch('pgadmin.tools.restore.current_user')
+    @patch('pgadmin.tools.restore.RestoreMessage')
+    @patch('pgadmin.tools.restore.filename_with_file_manager_path')
+    @patch('pgadmin.tools.restore.BatchProcess')
+    def runTest(self, batch_process_mock, filename_mock,
+                restore_message_mock, current_user_mock, server_mock):
+        class TestMockServer():
+            def __init__(self, name, host, port, id, username):
+                self.name = name
+                self.host = host
+                self.port = port
+                self.id = id
+                self.username = username
+
+        self.db_name = ''
+        self.server_id = parent_node_dict["server"][-1]["server_id"]
+
+        mock_obj = TestMockServer(self.class_params['name'],
+                                  self.class_params['host'],
+                                  self.class_params['port'],
+                                  self.server_id,
+                                  self.class_params['username']
+                                  )
+        mock_result = server_mock.query.filter_by.return_value
+        mock_result.first.return_value = mock_obj
+
+        filename_mock.return_value = self.params['file']
+
+        batch_process_mock.set_env_variables = MagicMock(
+            return_value=True
+        )
+        batch_process_mock.start = MagicMock(
+            return_value=True
+        )
+
+        server_response = server_utils.connect_server(self, self.server_id)
+        if server_response["info"] == "Server connected.":
+            db_owner = server_response['data']['user']['name']
+            self.data = database_utils.get_db_data(db_owner)
+            self.db_name = self.data['name']
+
+        url = self.url.format(self.server_id)
+
+        # Create the restore job
+        response = self.tester.post(url,
+                                    data=json.dumps(self.params),
+                                    content_type='html/json')
+        self.assertEquals(response.status_code, 200)
+        response_data = json.loads(response.data.decode('utf-8'))
+        job_id = response_data['data']['job_id']
+
+        assert restore_message_mock.called
+        assert batch_process_mock.called
+
+        if self.expected_cmd_opts:
+            for opt in self.expected_cmd_opts:
+                self.assertIn(
+                    opt,
+                    batch_process_mock.call_args_list[0][1]['args']
+                )
+        if self.not_expected_cmd_opts:
+            for opt in self.not_expected_cmd_opts:
+                self.assertNotIn(
+                    opt,
+                    batch_process_mock.call_args_list[0][1]['args']
+                )
diff --git a/web/pgadmin/tools/restore/tests/test_restore_message.py b/web/pgadmin/tools/restore/tests/test_restore_message.py
new file mode 100644
index 0000000..0b3e09d
--- /dev/null
+++ b/web/pgadmin/tools/restore/tests/test_restore_message.py
@@ -0,0 +1,85 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2018, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import sys
+
+from pgadmin.tools.restore import RestoreMessage
+from pgadmin.utils.route import BaseTestGenerator
+
+if sys.version_info < (3, 3):
+    from mock import patch
+else:
+    from unittest.mock import patch
+
+
+class RestoreMessageTest(BaseTestGenerator):
+    """Test the RestoreMessage class"""
+    scenarios = [
+        ('When restore object',
+         dict(
+             class_params=dict(
+                 sid=1,
+                 name='test_restore_server',
+                 port=5444,
+                 host='localhost',
+                 database='postgres',
+                 bfile='test_restore',
+                 args=[
+                     '--file',
+                     'restore_file',
+                     '--host',
+                     'localhost',
+                     '--port',
+                     '5444',
+                     '--username',
+                     'postgres',
+                     '--no-password',
+                     '--database',
+                     'postgres'
+                 ],
+                 cmd="/test_path/pg_restore"
+             ),
+             extected_msg="Restoring backup on the server "
+                          "'test_restore_server (localhost:5444)'...",
+             expetced_details_cmd='/test_path/pg_restore --file '
+                                  '"restore_file" --host "localhost"'
+                                  ' --port "5444" --username "postgres" '
+                                  '--no-password --database "postgres"'
+
+         ))
+    ]
+
+    @patch('pgadmin.tools.restore.Server')
+    @patch('pgadmin.tools.restore.current_user')
+    def runTest(self, current_user_mock, server_mock):
+        current_user_mock = 1
+
+        class TestMockServer():
+            def __init__(self, name, host, port):
+                self.name = name
+                self.host = host
+                self.port = port
+        mock_obj = TestMockServer(self.class_params['name'],
+                                  self.class_params['host'],
+                                  self.class_params['port'])
+        mock_result = server_mock.query.filter_by.return_value
+        mock_result.first.return_value = mock_obj
+
+        restore_obj = RestoreMessage(
+            self.class_params['sid'],
+            self.class_params['bfile'],
+            *self.class_params['args']
+        )
+
+        # Check the expected message returned
+        assert restore_obj.message == self.extected_msg
+
+        # Check the command
+        obj_details = restore_obj.details(self.class_params['cmd'],
+                                          self.class_params['args'])
+        self.assertIn(self.expetced_details_cmd, obj_details)
diff --git a/web/regression/python_test_utils/test_utils.py b/web/regression/python_test_utils/test_utils.py
index 3e517b6..d61c5d8 100644
--- a/web/regression/python_test_utils/test_utils.py
+++ b/web/regression/python_test_utils/test_utils.py
@@ -21,6 +21,8 @@ import config
 import regression
 from regression import test_setup
 
+from pgadmin.utils.preferences import Preferences
+
 SERVER_GROUP = test_setup.config_data['server_group']
 file_name = os.path.realpath(__file__)
 
@@ -86,7 +88,8 @@ def get_config_data():
                 "db_password": srv['db_password'],
                 "role": "",
                 "sslmode": srv['sslmode'],
-                "tablespace_path": srv.get('tablespace_path', None)
+                "tablespace_path": srv.get('tablespace_path', None),
+                "DEFAULT_BINARY_PATHS": srv.get('DEFAULT_BINARY_PATHS', None)
             }
             if 'db_type' in srv:
                 data['db_type'] = srv['db_type']
@@ -445,6 +448,13 @@ def delete_server_with_api(tester, sid):
         url = '/browser/server/obj/' + str(SERVER_GROUP) + "/"
         # Call API to delete the server
         response = tester.delete(url + str(sid))
+
+        cnt = 0
+        for s in regression.parent_node_dict["server"]:
+            if s['server_id'] == int(sid):
+                del regression.parent_node_dict["server"][cnt]
+            cnt += 1
+
     except Exception:
         traceback.print_exc(file=sys.stderr)
 
@@ -596,6 +606,47 @@ def get_db_server(sid):
     return connection

+def set_preference(default_binary_path):
+    conn = sqlite3.connect(config.TEST_SQLITE_PATH)
+    cur = conn.cursor()
+
+    perf = Preferences.module('paths')
+    pg_path_pref = perf.preference('pg_bin_dir')
+
+    user_pref = cur.execute(
+        'SELECT pid, uid FROM user_preferences where pid=%s' % pg_path_pref.pid
+    )
+    user_pref = user_pref.fetchone()
+
+    if user_pref:
+        cur.execute('UPDATE user_preferences SET value = ? WHERE pid = ?',
+                    (default_binary_path['pg'], pg_path_pref.pid))
+    else:
+        pg_pref_details = (pg_path_pref.pid, 1,
+                           default_binary_path['pg'])
+        cur.execute('INSERT INTO user_preferences(pid, uid, value)'
+                    ' VALUES (?,?,?)', pg_pref_details)
+
+    ppas_path_pref = perf.preference('ppas_bin_dir')
+
+    user_pref = cur.execute(
+        'SELECT pid, uid FROM user_preferences where pid=%s' %
+        ppas_path_pref.pid
+    )
+    user_pref = user_pref.fetchone()
+
+    if user_pref:
+        cur.execute('UPDATE user_preferences SET value = ? WHERE pid = ? ',
+                    (default_binary_path['ppas'], ppas_path_pref.pid))
+    else:
+        ppas_pref_details = (ppas_path_pref.pid, 1,
+                             default_binary_path['ppas'])
+        cur.execute('INSERT INTO user_preferences(pid, uid, value)'
+                    ' VALUES (?,?,?)', ppas_pref_details)
+
+    conn.commit()
+
+
 def remove_db_file():
     """This function use to remove SQLite DB file"""
     if os.path.isfile(config.TEST_SQLITE_PATH):
diff --git a/web/regression/runtests.py b/web/regression/runtests.py
index d786692..21e4e35 100644
--- a/web/regression/runtests.py
+++ b/web/regression/runtests.py
@@ -114,6 +114,9 @@ test_client = app.test_client()
 driver = None
 app_starter = None
 handle_cleanup = None
+app.PGADMIN_RUNTIME = True
+if config.SERVER_MODE is True:
+    app.PGADMIN_RUNTIME = False

@@ -234,7 +237,6 @@ def get_test_modules(arguments):
     # Sort module list so that test suite executes the test cases sequentially
     module_list = TestsGeneratorRegistry.registry.items()
     module_list = sorted(module_list, key=lambda module_tuple: module_tuple[0])
-
     return module_list

@@ -393,6 +395,15 @@ if __name__ == '__main__':
             # Create test server
             server_information = test_utils.create_parent_server_node(server)
 
+            if server['DEFAULT_BINARY_PATHS'] is not None:
+                test_utils.set_preference(server['DEFAULT_BINARY_PATHS'])
+
+                config.DEFAULT_BINARY_PATHS = {
+                    "pg": str(server['DEFAULT_BINARY_PATHS']['pg']),
+                    "ppas": str(server['DEFAULT_BINARY_PATHS']['ppas']),
+                    "gpdb": ""
+                }
+
             suite = get_suite(test_module_list,
                               server,
                               test_client,
diff --git a/web/regression/test_config.json.in b/web/regression/test_config.json.in
index ebc1466..cb6b98c 100644
--- a/web/regression/test_config.json.in
+++ b/web/regression/test_config.json.in
@@ -23,7 +23,12 @@
       "maintenance_db": "postgres",
       "sslmode": "prefer",
       "tablespace_path": "",
-      "enabled": true
+      "enabled": true,
+      "DEFAULT_BINARY_PATHS": {
+        "pg": "/opt/PostgreSQL/9.4/bin/",
+        "ppas": "/opt/edb/as10/bin/",
+        "gpdb": ""
+      }
     }
   ],
   "server_update_data": [

---

From: Dave Page <[email-masked]>
Date: Tue, 29 May 2018 15:35:39 -0400

Hi

> 2. End to end regression test cases

Thanks. I've yet to be able to run the feature tests successfully. Here's
what I've found so far:

1) DEFAULT_BINARY_PATHS should be default_binary_paths in the JSON config
file.

2) I've hit screensize related issues:

======================================================================

ERROR: runTest
(pgadmin.feature_tests.pg_utilities_maintenance_test.PGUtilitiesMaintenanceFeatureTest)

Test for PG maintenance: database

----------------------------------------------------------------------

Traceback (most recent call last):

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py",
line 56, in runTest

    self._open_maintenance_dialogue()

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py",
line 75, in _open_maintenance_dialogue

    "*[.='" + self.table_name + "']/../*[@class='aciTreeItem'"

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py",
line 80, in click

    self._execute(Command.CLICK_ELEMENT)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py",
line 628, in _execute

    return self._parent.execute(command, params)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py",
line 312, in execute

    self.error_handler.check_response(response)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py",
line 242, in check_response

    raise exception_class(message, screen, stacktrace)

WebDriverException: Message: unknown error: Element <span
class="aciTreeItem">...</span> is not clickable at point (223, 604). Other
element would receive the click: <div class="wcFrameCenter
wcPanelBackground wcScrollableX wcScrollableY" style="left: 0px; right:
0px; bottom: 0px;">...</div>

  (Session info: chrome=66.0.3359.181)

  (Driver info: chromedriver=2.38.552518
(183d19265345f54ce39cbb94cf81ba5f15905011),platform=Mac OS X 10.12.6 x86_64)

3) One time the test did start, but then I saw this failure:

======================================================================

ERROR: runTest
(pgadmin.feature_tests.pg_utilities_backup_restore_test.PGUtilitiesBackupFeatureTest)

Test for PG utilities - Backup and Restore

----------------------------------------------------------------------

Traceback (most recent call last):

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py",
line 93, in runTest

    self.page.fill_input_by_field_name("file", "test_backup_file")

  File
"/Users/dpage/git/pgadmin4/web/regression/feature_utils/pgadmin_page.py",
line 211, in fill_input_by_field_name

    self.wait_for_input_field_content(field_name, field_content)

  File
"/Users/dpage/git/pgadmin4/web/regression/feature_utils/pgadmin_page.py",
line 251, in wait_for_input_field_content

    "field to contain '" + str(content) + "'", input_field_has_content

  File
"/Users/dpage/git/pgadmin4/web/regression/feature_utils/pgadmin_page.py",
line 337, in _wait_for

    "Timed out waiting for " + waiting_for_message

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/selenium/webdriver/support/wait.py",
line 80, in until

    raise TimeoutException(message, screen, stacktrace)

TimeoutException: Message: Timed out waiting for field to contain
'test_backup_file'

(with screenshot attached)

Thanks.

>> For the feature tests, we realized we had to update the configuration,
>> and we did that, but we get the following error attached. We spent some
>> time trying to understand the problem but we were not successful.
>>
>>
>> Codewise:

-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

---

From: Khushboo Vashi <[email-masked]>
Date: Wed, 30 May 2018 10:13:49 +0530

On Wed, May 30, 2018 at 1:05 AM, Dave Page <[email-masked]> wrote:

> Will do.

> ERROR: runTest (pgadmin.feature_tests.pg_utilities_maintenance_test.
> PGUtilitiesMaintenanceFeatureTest)
>
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/pg_
> utilities_maintenance_test.py", line 56, in runTest
>
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/pg_
> utilities_maintenance_test.py", line 75, in _open_maintenance_dialogue
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-
> packages/selenium/webdriver/remote/webelement.py", line 80, in click
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-
> packages/selenium/webdriver/remote/webelement.py", line 628, in _execute
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-
> packages/selenium/webdriver/remote/webdriver.py", line 312, in execute
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-
> packages/selenium/webdriver/remote/errorhandler.py", line 242, in
> check_response
>
>   (Driver info: chromedriver=2.38.552518 (183d19265345f54ce39cbb94cf81ba5f15905011),platform=Mac
> OS X 10.12.6 x86_64)
>
> ERROR: runTest (pgadmin.feature_tests.pg_utilities_backup_restore_test.
> PGUtilitiesBackupFeatureTest)
>
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/pg_
> utilities_backup_restore_test.py", line 93, in runTest
>
>   File "/Users/dpage/git/pgadmin4/web/regression/feature_utils/pgadmin_page.py",
>   File "/Users/dpage/git/pgadmin4/web/regression/feature_utils/pgadmin_page.py",
>   File "/Users/dpage/git/pgadmin4/web/regression/feature_utils/pgadmin_page.py",
> line 337, in _wait_for
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-
> packages/selenium/webdriver/support/wait.py", line 80, in until
>
> I have ran the feature tests with multiple servers many times but didn't
get a single failure.
I have asked Akshay to run on his machine, let see what he gets.

>>> We passed the tests through our CI the feature tests are not passing,
>>> but the linter fails:
>>>
>>> - Looks like there is a bug report in this area of the code and we do
>>> not have coverage for it: https://redmine.postgresql.org/issues/3232
>>> `/usr/lib/postgresql/{{db_version}}/bin`, which makes us think that
>>> this configuration should live near the server configuration, maybe? Also
>>> to maintain coherency on the naming maybe we should make it all lower case.

---

From: Khushboo Vashi <[email-masked]>
Date: Thu, 31 May 2018 10:46:12 +0530

Hi,

Please find the attached updated patch with the fixes.
The test cases were only failing on MAC not on Linux.

Thanks,
Khushboo

On Wed, May 30, 2018 at 10:13 AM, Khushboo Vashi <
[email-masked]> wrote:

>> ERROR: runTest (pgadmin.feature_tests.pg_util
>> ities_maintenance_test.PGUtilitiesMaintenanceFeatureTest)
>>
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py",
>> line 56, in runTest
>>
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py",
>>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packa
>> ges/selenium/webdriver/remote/webelement.py", line 80, in click
>>
>>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packa
>> ges/selenium/webdriver/remote/webelement.py", line 628, in _execute
>>
>>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packa
>> ges/selenium/webdriver/remote/webdriver.py", line 312, in execute
>>
>>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packa
>> ges/selenium/webdriver/remote/errorhandler.py", line 242, in
>> check_response
>>
>> ERROR: runTest (pgadmin.feature_tests.pg_util
>> ities_backup_restore_test.PGUtilitiesBackupFeatureTest)
>>
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py",
>> line 93, in runTest
>>
>>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packa
>> ges/selenium/webdriver/support/wait.py", line 80, in until
>>

---

From: Victoria Henry <[email-masked]>
Date: Thu, 31 May 2018 12:30:42 -0400

Hi there,

We've been noticing some issues with the tests on both our CI and local Mac
workstations.

   1. When the following code blocks are invoked - we get plenty of
   app.context() issues. It must not be valid when running tests.

​

from pgadmin.utils.driver import get_driver
driver = get_driver(PG_DEFAULT_DRIVER)
manager = driver.connection_manager(self.sid)

host = manager.local_bind_host if manager.use_ssh_tunnel else s.host
port = manager.local_bind_port if manager.use_ssh_tunnel else s.port

2. When we finally enable

"default_binary_paths": {

in our test_config, we get more failing tests that look like:

======================================================================
FAIL: runTest (pgadmin.tools.restore.tests.test_restore_create_job_unit_test.RestoreCreateJobTest)
When restore object with option - Miscellaneous
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/pivotal/.pyenv/versions/3.6.5/lib/python3.6/unittest/mock.py",
line 1179, in patched
    return func(*args, **keywargs)
  File "/Users/pivotal/workspace/pgadmin4/web/pgadmin/tools/restore/tests/test_restore_create_job_unit_test.py",
line 295, in runTest
    self.assertEquals(response.status_code, 200)
AssertionError: 410 != 200

And

When restore object with the sections options ... 2018-05-31
12:24:42,988: ERROR    pgadmin:    illegal environment variable name
Traceback (most recent call last):
  File "/Users/pivotal/workspace/pgadmin4/web/pgadmin/tools/restore/__init__.py",
line 352, in create_restore_job
    manager.export_password_env(p.id)
  File "/Users/pivotal/workspace/pgadmin4/web/pgadmin/utils/driver/psycopg2/server_manager.py",
line 365, in export_password_env
    os.environ[str(env)] = password
  File "/Users/pivotal/.pyenv/versions/3.6.5/lib/python3.6/os.py",
line 675, in __setitem__
    self.putenv(key, value)
ValueError: illegal environment variable name
FAIL

​

Sincerely,

Victoria && Anthony

On Thu, May 31, 2018 at 1:16 AM Khushboo Vashi <
[email-masked]> wrote:

>>> Thanks. I've yet to be able to run the feature tests successfully.
>>> Here's what I've found so far:
>>>
>>> 1) DEFAULT_BINARY_PATHS should be default_binary_paths in the JSON
>>> config file.
>>>
>>> Will do.
>>

---

From: Khushboo Vashi <[email-masked]>
Date: Fri, 1 Jun 2018 16:36:35 +0530

Hi Victoria,

Thanks for reviewing the patch.
The tests were failing due to the latest commit
#2b4605a9d390cb44e5dfe9967c3adf2b28d04f1f  - Ensure
backup/restore/maintenance work via SSH tunnels. Fixes #3355

I have fixed the issues and attached the updated patch.

Thanks,
Khushboo

On Thu, May 31, 2018 at 10:00 PM, Victoria Henry <[email-masked]> wrote:

> Hi there,
>
> We've been noticing some issues with the tests on both our CI and local
> Mac workstations.
>
>   File "/Users/pivotal/.pyenv/versions/3.6.5/lib/python3.6/unittest/mock.py", line 1179, in patched
>   File "/Users/pivotal/workspace/pgadmin4/web/pgadmin/tools/restore/tests/test_restore_create_job_unit_test.py", line 295, in runTest
> When restore object with the sections options ... 2018-05-31 12:24:42,988: ERROR    pgadmin:    illegal environment variable name
>   File "/Users/pivotal/workspace/pgadmin4/web/pgadmin/tools/restore/__init__.py", line 352, in create_restore_job
>   File "/Users/pivotal/workspace/pgadmin4/web/pgadmin/utils/driver/psycopg2/server_manager.py", line 365, in export_password_env
>   File "/Users/pivotal/.pyenv/versions/3.6.5/lib/python3.6/os.py", line 675, in __setitem__
>     self.putenv(key, value)
>>>>   (Driver info: chromedriver=2.38.552518 (
>>>> 183d19265345f54ce39cbb94cf81ba5f15905011),platform=Mac OS X 10.12.6
>>>> x86_64)
>>>>
>>>> I have ran the feature tests with multiple servers many times but
>>> didn't get a single failure.
>>>>>> We reviewed the patch and it is very nice to see some more coverage
>>>>>> in this area. Good job :D
>>>>>>
>>>>>> For the feature tests, we realized we had to update the
>>>>>> configuration, and we did that, but we get the following error attached. We
>>>>>> spent some time trying to understand the problem but we were not successful.
>>>>>>
>>>>>>
>>>>>> Codewise:
>>>>>>> Please find the attached patch which covers test cases for the
>>>>>>> backup module (RM #3206).
>>>>>>>
>>>>>>> 1. Unit test cases
index 0000000..b4c1bb2
@@ -0,0 +1,140 @@
+        if self.server['default_binary_paths'] is None:
+                "default_binary_paths is not set for the server {0}".format(
+        self.wait = WebDriverWait(self.page.driver, 20)
+        self.wait.until(EC.presence_of_element_located(
+            (
+                By.XPATH,
+                "//label[contains(string(), 'Filename')]"
+        self.wait.until(EC.element_to_be_clickable(
+            (By.CSS_SELECTOR, ".browse_file_input"))).click()
+        self.page.fill_input_by_field_name("file", "test_backup")
+        self.assertIn("test_backup", str(command))
+        self.wait.until(EC.presence_of_element_located(
+            (
+                By.XPATH,
+                "//label[contains(string(), 'Filename')]"
+        self.wait.until(EC.element_to_be_clickable(
+            (By.CSS_SELECTOR, ".browse_file_input"))).click()
+        self.page.fill_input_by_field_name("file", "test_backup")
+        self.assertIn("test_backup", str(command))
index 0000000..7806268
+        if self.server['default_binary_paths'] is None:
+                "default_binary_paths is not set for the server {0}".format(
+        self.wait = WebDriverWait(self.page.driver, 20)
diff --git a/web/pgadmin/tools/backup/__init__.py b/web/pgadmin/tools/backup/__init__.py
index 125db80..0513365 100644
--- a/web/pgadmin/tools/backup/__init__.py
+++ b/web/pgadmin/tools/backup/__init__.py
@@ -109,8 +109,7 @@ class BackupMessage(IProcessDesc):
             else:
                 self.cmd += cmdArg(arg)
 
-    @property
-    def message(self):
+    def get_server_details(self):
         # Fetch the server details like hostname, port, roles etc
         s = Server.query.filter_by(
             id=self.sid, user_id=current_user.id
@@ -123,13 +122,19 @@ class BackupMessage(IProcessDesc):
         host = manager.local_bind_host if manager.use_ssh_tunnel else s.host
         port = manager.local_bind_port if manager.use_ssh_tunnel else s.port
 
+        return s.name, host, port
+
+    @property
+    def message(self):
+        name, host, port = self.get_server_details()
+
         if self.backup_type == BACKUP.OBJECT:
             return _(
                 "Backing up an object on the server '{0}' "
                 "from database '{1}'..."
             ).format(
                 "{0} ({1}:{2})".format(
-                    s.name, host, port
+                    name, host, port
                 ),
                 self.database
             )
@@ -137,13 +142,13 @@ class BackupMessage(IProcessDesc):
             return _("Backing up the global objects on "
                      "the server '{0}'...").format(
                 "{0} ({1}:{2})".format(
-                    s.name, host, port
+                    name, host, port
                 )
             )
         elif self.backup_type == BACKUP.SERVER:
             return _("Backing up the server '{0}'...").format(
                 "{0} ({1}:{2})".format(
-                    s.name, host, port
+                    name, host, port
                 )
             )
         else:
@@ -151,17 +156,7 @@ class BackupMessage(IProcessDesc):
             return "Unknown Backup"
 
     def details(self, cmd, args):
-        # Fetch the server details like hostname, port, roles etc
-        s = Server.query.filter_by(
-            id=self.sid, user_id=current_user.id
-        ).first()
-
-        from pgadmin.utils.driver import get_driver
-        driver = get_driver(PG_DEFAULT_DRIVER)
-        manager = driver.connection_manager(self.sid)
-
-        host = manager.local_bind_host if manager.use_ssh_tunnel else s.host
-        port = manager.local_bind_port if manager.use_ssh_tunnel else s.port
+        name, host, port = self.get_server_details()
 
         res = '<div class="h5">'
 
@@ -171,7 +166,7 @@ class BackupMessage(IProcessDesc):
                 "from database '{1}'..."
             ).format(
                 "{0} ({1}:{2})".format(
-                    html.safe_str(s.name),
+                    html.safe_str(name),
                     html.safe_str(host),
                     html.safe_str(port),
                 ),
@@ -181,7 +176,7 @@ class BackupMessage(IProcessDesc):
             res += _("Backing up the global objects on "
                      "the server '{0}'...").format(
                 "{0} ({1}:{2})".format(
-                    html.safe_str(s.name),
+                    html.safe_str(name),
                     html.safe_str(host),
                     html.safe_str(port)
                 )
@@ -189,7 +184,7 @@ class BackupMessage(IProcessDesc):
         elif self.backup_type == BACKUP.SERVER:
             res += _("Backing up the server '{0}'...").format(
                 "{0} ({1}:{2})".format(
-                    html.safe_str(s.name),
+                    html.safe_str(name),
                     html.safe_str(host),
                     html.safe_str(port)
                 )
index 0000000..a376a3b
@@ -0,0 +1,463 @@
+        if self.server['default_binary_paths'] is None:
+                "default_binary_paths is not set for the server {0}".format(
+    @patch('pgadmin.utils.driver.psycopg2.server_manager.ServerManager.'
+           'export_password_env')
+    def runTest(self, export_password_env_mock, batch_process_mock,
+                filename_mock, backup_message_mock,
+                current_user_mock, server_mock):
+        export_password_env_mock.return_value = True
index 0000000..34eacc9
@@ -0,0 +1,149 @@
+    @patch('pgadmin.tools.backup.BackupMessage.get_server_details')
+    def runTest(self, get_server_details_mock):
+        get_server_details_mock.return_value = \
+            self.class_params['name'],\
+            self.class_params['host'],\
+            self.class_params['port']
index 0000000..c074ca5
@@ -0,0 +1,212 @@
+    @patch('pgadmin.tools.backup.BackupMessage.get_server_details')
+    def runTest(self, current_user_mock, current_user, db_mock,
+                current_app_mock, popen_mock, get_server_details_mock):
+        get_server_details_mock.return_value = \
+            self.class_params['name'],\
+            self.class_params['host'],\
+            self.class_params['port']
index 0000000..d76a3c7
+                 file='test_backup',
+        if self.server['default_binary_paths'] is None:
+                "default_binary_paths is not set for the server {0}".format(
index 0000000..1e01f1d
@@ -0,0 +1,140 @@
+        if self.server['default_binary_paths'] is None:
+                "default_binary_paths is not set for the server {0}".format(
index 0000000..64d0d1d
@@ -0,0 +1,199 @@
+        if self.server['default_binary_paths'] is None:
+                "default_binary_paths is not set for the server {0}".format(
+    @patch('pgadmin.utils.driver.psycopg2.server_manager.ServerManager.'
+           'export_password_env')
+    def runTest(self, export_password_env_mock,
+                batch_process_mock, message_mock, server_mock):
+        export_password_env_mock.return_value = True
index 45d3816..58bc251 100644
@@ -86,8 +86,7 @@ class RestoreMessage(IProcessDesc):
             else:
                 self.cmd += cmdArg(arg)
 
-    @property
-    def message(self):
+    def get_server_details(self):
         # Fetch the server details like hostname, port, roles etc
         s = Server.query.filter_by(
             id=self.sid, user_id=current_user.id
@@ -100,30 +99,25 @@ class RestoreMessage(IProcessDesc):
         host = manager.local_bind_host if manager.use_ssh_tunnel else s.host
         port = manager.local_bind_port if manager.use_ssh_tunnel else s.port
 
+        return s.name, host, port
+
+    @property
+    def message(self):
+        name, host, port = self.get_server_details()
+
         return _("Restoring backup on the server '{0}'...").format(
-            "{0} ({1}:{2})".format(s.name, host, port),
+            "{0} ({1}:{2})".format(name, host, port),
         )
 
     def details(self, cmd, args):
-        # Fetch the server details like hostname, port, roles etc
-        s = Server.query.filter_by(
-            id=self.sid, user_id=current_user.id
-        ).first()
-
-        from pgadmin.utils.driver import get_driver
-        driver = get_driver(PG_DEFAULT_DRIVER)
-        manager = driver.connection_manager(self.sid)
-
-        host = manager.local_bind_host if manager.use_ssh_tunnel else s.host
-        port = manager.local_bind_port if manager.use_ssh_tunnel else s.port
-
+        name, host, port = self.get_server_details()
         res = '<div class="h5">'
 
         res += html.safe_str(
             _(
                 "Restoring backup on the server '{0}'..."
             ).format(
-                "{0} ({1}:{2})".format(s.name, host, port)
+                "{0} ({1}:{2})".format(name, host, port)
             )
         )
 
@@ -206,6 +200,7 @@ def create_restore_job(sid):
 
     if _file is None:
index 0000000..28d692a
@@ -0,0 +1,154 @@
+    @patch('pgadmin.tools.restore.RestoreMessage.get_server_details')
+    def runTest(self, current_user_mock, current_user, db_mock,
+                current_app_mock, popen_mock, get_server_details_mock):
+        get_server_details_mock.return_value = \
+            self.class_params['name'],\
+            self.class_params['host'],\
+            self.class_params['port']
index 0000000..0953544
@@ -0,0 +1,194 @@
+        if self.server['default_binary_paths'] is None:
+                "default_binary_paths is not set for the server {0}".format(
index 0000000..2829cd8
@@ -0,0 +1,318 @@
+        if self.server['default_binary_paths'] is None:
+                "default_binary_paths is not set for the server {0}".format(
+    @patch('pgadmin.utils.driver.psycopg2.server_manager.ServerManager.'
+           'export_password_env')
+    def runTest(self, export_password_env_mock, batch_process_mock,
+                filename_mock, restore_message_mock,
+                current_user_mock, server_mock):
+        export_password_env_mock.return_value = True
index 0000000..bb45286
@@ -0,0 +1,76 @@
+    @patch('pgadmin.tools.restore.RestoreMessage.get_server_details')
+    def runTest(self, get_server_details_mock):
+        get_server_details_mock.return_value = \
+            self.class_params['name'],\
+            self.class_params['host'],\
+            self.class_params['port']
index 3e517b6..d5d3a0f 100644

+                "default_binary_paths": srv.get('default_binary_paths', None)

index d786692..0a1d48e 100644

 
+            if server['default_binary_paths'] is not None:
+                test_utils.set_preference(server['default_binary_paths'])
+
+                config.DEFAULT_BINARY_PATHS = {
+                    "pg": str(server['default_binary_paths']['pg']),
+                    "ppas": str(server['default_binary_paths']['ppas']),
+                    "gpdb": ""
+                }
+
             suite = get_suite(test_module_list,
                               server,
                               test_client,
diff --git a/web/regression/test_config.json.in b/web/regression/test_config.json.in
index ebc1466..15b133a 100644
--- a/web/regression/test_config.json.in
+++ b/web/regression/test_config.json.in
@@ -23,7 +23,12 @@
       "maintenance_db": "postgres",
       "sslmode": "prefer",
       "tablespace_path": "",
-      "enabled": true
+      "enabled": true,
+      "default_binary_paths": {
+        "pg": "/opt/PostgreSQL/9.4/bin/",
+        "ppas": "/opt/edb/as10/bin/",
+        "gpdb": ""
+      }
     }
   ],
   "server_update_data": [

---

From: Dave Page <[email-masked]>
Date: Fri, 1 Jun 2018 17:31:11 -0400

Hi

This looks good, except that it's leaving the test_restore_database behind.
Can we clean that up please?

Thanks.

On Fri, Jun 1, 2018 at 7:06 AM, Khushboo Vashi <
[email-masked]> wrote:

> The tests were failing due to the latest commit #
> 2b4605a9d390cb44e5dfe9967c3adf2b28d04f1f  - Ensure
>>>>>>> We passed the tests through our CI the feature tests are not
>>>>>>> passing, but the linter fails:
>>>>>>>
>>>>>>> - Looks like there is a bug report in this area of the code and we
>>>>>>> do not have coverage for it: https://redmine.postgresql
>>>>>>> .org/issues/3232
>>>>>>>   Looks like in some of the unit tests we only have happy path
>>>>>>> tests, maybe we should see if there are any sad paths that also need
>>>>>>> coverage.
>>>>>>>

---

From: Khushboo Vashi <[email-masked]>
Date: Mon, 4 Jun 2018 11:05:49 +0530

On Sat, Jun 2, 2018 at 3:01 AM, Dave Page <[email-masked]> wrote:

> Hi
>
> This looks good, except that it's leaving the test_restore_database
> behind. Can we clean that up please?
>
> PFA updated patch.

>>>>>>>> `/usr/lib/postgresql/{{db_version}}/bin`, which makes us think
>>>>>>>> that this configuration should live near the server configuration, maybe?
>>>>>>>> Also to maintain coherency on the naming maybe we should make it all lower
>>>>>>>> case.

---

From: Joao De Almeida Pereira <[email-masked]>
Date: Mon, 4 Jun 2018 11:11:01 -0400

Hi Khushboo,

Some tests are failing in greenplum:
https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-tests/builds/108
The piece of code responsible for the error is:

if server['default_binary_paths'] is not None:
    test_utils.set_preference(server['default_binary_paths'])

    config.DEFAULT_BINARY_PATHS = {
        "pg": str(server['default_binary_paths']['pg']),
        "ppas": str(server['default_binary_paths']['ppas']),
        "gpdb": ""
    }

test_backup_utils.py file name is misleading, these are not tests, are
helpers.
​

Thanks
Victoria & Joao

On Mon, Jun 4, 2018 at 1:36 AM Khushboo Vashi <
[email-masked]> wrote:

>>>>>>>> please find the attached updated patch for the test cases of
>>>>>>>> Backup, Restore and Maintenance modules which includes:
>>>>>>>>
>>>>>>>> 1. Unit test cases
>>>>>>>>> We reviewed the patch and it is very nice to see some more
>>>>>>>>> coverage in this area. Good job :D
>>>>>>>>>
>>>>>>>>> do not have coverage for it:
>>>>>>>>> https://redmine.postgresql.org/issues/3232
>>>>>>>>> The configuration change, maybe need to be updated. When we
>>>>>>>>> install multiple versions of postgres the binaries live in

---

From: Khushboo Vashi <[email-masked]>
Date: Tue, 5 Jun 2018 09:09:51 +0530

On Mon, Jun 4, 2018 at 8:41 PM, Joao De Almeida Pereira <
[email-masked]> wrote:

> https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/
> pipelines/pgadmin-patch/jobs/run-tests/builds/108
> Can you send me the test_config.json file?  The above code sets the paths
to the SQLite database and through the logs couldn't figure out the exact
failure.

>>>>> We've been noticing some issues with the tests on both our CI and
>>>>> local Mac workstations.
>>>>>
>>>>>>>> ERROR: runTest (pgadmin.feature_tests.pg_
>>>>>>>> utilities_maintenance_test.PGUtilitiesMaintenanceFeatureTest)
>>>>>>>>
>>>>>>>> 183d19265345f54ce39cbb94cf81ba5f15905011),platform=Mac OS X
>>>>>>>> 10.12.6 x86_64)
>>>>>>>>
>>>>>>>> ERROR: runTest (pgadmin.feature_tests.pg_
>>>>>>>> utilities_backup_restore_test.PGUtilitiesBackupFeatureTest)
>>>>>>>>
>>>>>>>>>> - Looks like there is a bug report in this area of the code and
>>>>>>>>>> we do not have coverage for it: https://redmine.
>>>>>>>>>> postgresql.org/issues/3232

---

From: Dave Page <[email-masked]>
Date: Tue, 5 Jun 2018 09:06:42 +0100

Hi

> to the SQLite database and through the logs couldn't figure out the exact

It seems clear from the code shown that it's not setting the binary paths
for gpdb database servers. Shouldn't it be something like:

    config.DEFAULT_BINARY_PATHS = {
        "pg": str(server['default_binary_paths']['pg']),
        "ppas": str(server['default_binary_paths']['ppas']),
        "gpdb": str(server['default_binary_paths']['gpdb'])
    }

>>>>>>>>>   File "/Users/dpage/git/pgadmin4/web
>>>>>>>>> /pgadmin/feature_tests/pg_utilities_maintenance_test.py", line
>>>>>>>>> 56, in runTest
>>>>>>>>>
>>>>>>>>>   File "/Users/dpage/git/pgadmin4/web
>>>>>>>>> /pgadmin/feature_tests/pg_utilities_maintenance_test.py", line
>>>>>>>>> 75, in _open_maintenance_dialogue
>>>>>>>>>
>>>>>>>>>   File "/Users/dpage/.virtualenvs/pga
>>>>>>>>> dmin4/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py",
>>>>>>>>> line 80, in click
>>>>>>>>>
>>>>>>>>>   File "/Users/dpage/.virtualenvs/pga
>>>>>>>>> dmin4/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py",
>>>>>>>>> line 628, in _execute
>>>>>>>>>
>>>>>>>>>   File "/Users/dpage/.virtualenvs/pga
>>>>>>>>> dmin4/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py",
>>>>>>>>> line 312, in execute
>>>>>>>>>
>>>>>>>>>   File "/Users/dpage/.virtualenvs/pga
>>>>>>>>> dmin4/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py",
>>>>>>>>>   File "/Users/dpage/git/pgadmin4/web
>>>>>>>>> /pgadmin/feature_tests/pg_utilities_backup_restore_test.py", line
>>>>>>>>> 93, in runTest
>>>>>>>>>
>>>>>>>>>   File "/Users/dpage/git/pgadmin4/web
>>>>>>>>> /regression/feature_utils/pgadmin_page.py", line 211, in
>>>>>>>>> fill_input_by_field_name
>>>>>>>>>
>>>>>>>>>   File "/Users/dpage/git/pgadmin4/web
>>>>>>>>> /regression/feature_utils/pgadmin_page.py", line 251, in
>>>>>>>>> wait_for_input_field_content
>>>>>>>>>
>>>>>>>>>   File "/Users/dpage/git/pgadmin4/web
>>>>>>>>> /regression/feature_utils/pgadmin_page.py", line 337, in _wait_for
>>>>>>>>>
>>>>>>>>>   File "/Users/dpage/.virtualenvs/pga
>>>>>>>>> dmin4/lib/python2.7/site-packages/selenium/webdriver/support/wait.py",
>>>>>>>>> line 80, in until
>>>>>>>>>
>>>>>>>>>>> we do not have coverage for it: https://redmine.postgresql
>>>>>>>>>>> .org/issues/3232

---

From: Khushboo Vashi <[email-masked]>
Date: Tue, 5 Jun 2018 14:07:48 +0530

On Tue, Jun 5, 2018 at 1:36 PM, Dave Page <[email-masked]> wrote:

>>> Can you send me the test_config.json file?  The above code sets the
>> paths to the SQLite database and through the logs couldn't figure out the
>> exact failure.
>>
>
> Without this code, the test cases should work as I already set  paths
through below code.

>>>>>>>>>> Thanks. I've yet to be able to run the feature tests
>>>>>>>>>> successfully. Here's what I've found so far:
>>>>>>>>>>
>>>>>>>>>> 1) DEFAULT_BINARY_PATHS should be default_binary_paths in the
>>>>>>>>>> JSON config file.
>>>>>>>>>>
>>>>>>>>>> Will do.
>>>>>>>>>
>>>>>>>>>> /pgadmin/feature_tests/pg_utilities_backup_restore_test.py",
>>>>>>>>>> line 93, in runTest
>>>>>>>>>>

---

From: Dave Page <[email-masked]>
Date: Tue, 5 Jun 2018 09:39:30 +0100

>     test_utils.set_preference(server['default_binary_paths'])
In that case, why is the code above required at all?

>>>>>>>>    1. When the following code blocks are invoked - we get plenty
>>>>>>>>    of app.context() issues. It must not be valid when running
>>>>>>>>    tests.
>>>>>>>>
>>>>>>>> ​
>>>>>>>>
>>>>>>>>>>> TimeoutException: Message: Timed out waiting for field to
>>>>>>>>>>> contain 'test_backup_file'
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> I have ran the feature tests with multiple servers many times
>>>>>>>>>> but didn't get a single failure.
>>>>>>>>>>>>> - Looks like there is a bug report in this area of the code
>>>>>>>>>>>>> and we do not have coverage for it: https://redmine.postgresql
>>>>>>>>>>>>> .org/issues/3232
>>>>>>>>>>>>> `/usr/lib/postgresql/{{db_version}}/bin`, which makes us
>>>>>>>>>>>>> think that this configuration should live near the server configuration,
>>>>>>>>>>>>> maybe? Also to maintain coherency on the naming maybe we should make it all
>>>>>>>>>>>>> lower case.
>>>>>>>>>>>>>> Please find the attached patch which covers test cases for
>>>>>>>>>>>>>> the backup module (RM #3206).
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 1. Unit test cases

---

From: Khushboo Vashi <[email-masked]>
Date: Tue, 5 Jun 2018 14:20:52 +0530

On Tue, Jun 5, 2018 at 2:09 PM, Dave Page <[email-masked]> wrote:

>>> It seems clear from the code shown that it's not setting the binary
>>> paths for gpdb database servers. Shouldn't it be something like:
>>>
> My bad. Removed this code and also updated set_preference function for
greenplum database.
Please find the attached updated patch.

>>>>>>>> On Thu, May 31, 2018 at 10:00 PM, Victoria Henry <[email-masked]
>>>>>>>> > wrote:
>>>>>>>>
>>>>>>>>> Hi there,
>>>>>>>>>
>>>>>>>>>>>>>> and we do not have coverage for it:
>>>>>>>>>>>>>>   Looks like in some of the unit tests we only have happy
>>>>>>>>>>>>>> path tests, maybe we should see if there are any sad paths that also need
>>>>>>>>>>>>>> coverage.
>>>>>>>>>>>>>>

---

From: Victoria Henry <[email-masked]>
Date: Tue, 5 Jun 2018 19:43:39 -0400

Hi Khushboo

The tests are still failing and seems flaky:
https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines/pgadmin-patch/jobs/run-tests/builds/113

Sincerely,

Victoria

On Tue, Jun 5, 2018 at 4:50 AM Khushboo Vashi <
[email-masked]> wrote:

>>>>> test_backup_utils.py file name is misleading, these are not tests,
>>>>>> are helpers.
>>>>>> ​
>>>>>>
>>>>>>
>>>>>> Thanks
>>>>>> Victoria & Joao
>>>>>>

---

From: Khushboo Vashi <[email-masked]>
Date: Wed, 6 Jun 2018 09:37:51 +0530

Hi Victoria,

As per the logs, Restore job is failing only for GPDB. As I don't have
setup for the greenplum database, can you please check this functionality
works well in pgAdmin4 with GPDB?

Thanks,
Khushboo

On Wed, Jun 6, 2018 at 5:13 AM, Victoria Henry <[email-masked]> wrote:

> pipelines/pgadmin-patch/jobs/run-tests/builds/113
>
> Sincerely,
>
> Victoria
>
>>>>>>>>> This looks good, except that it's leaving the
>>>>>>>>> test_restore_database behind. Can we clean that up please?
>>>>>>>>>
>>>>>>>>> PFA updated patch.
>>>>>>>>
>>>>>>>>> Thanks.
>>>>>>>>>
>>>>>>>>>>> We've been noticing some issues with the tests on both our CI
>>>>>>>>>>> and local Mac workstations.
>>>>>>>>>>>
>>>>>>>>>>>    1. When the following code blocks are invoked - we get
>>>>>>>>>>>    plenty of app.context() issues. It must not be valid when
>>>>>>>>>>>    running tests.
>>>>>>>>>>>
>>>>>>>>>>> ​
>>>>>>>>>>>
>>>>>>>>>>>>>>   File "/Users/dpage/git/pgadmin4/
>>>>>>>>>>>>>> web/pgadmin/feature_tests/pg_utilities_maintenance_test.py",
>>>>>>>>>>>>>> line 56, in runTest
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>   File "/Users/dpage/git/pgadmin4/
>>>>>>>>>>>>>> web/pgadmin/feature_tests/pg_utilities_maintenance_test.py",
>>>>>>>>>>>>>>   File "/Users/dpage/.virtualenvs/
>>>>>>>>>>>>>> pgadmin4/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py",
>>>>>>>>>>>>>> line 80, in click
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>   File "/Users/dpage/.virtualenvs/
>>>>>>>>>>>>>> pgadmin4/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py",
>>>>>>>>>>>>>> line 628, in _execute
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>   File "/Users/dpage/.virtualenvs/
>>>>>>>>>>>>>> pgadmin4/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py",
>>>>>>>>>>>>>> line 312, in execute
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>   File "/Users/dpage/.virtualenvs/
>>>>>>>>>>>>>> pgadmin4/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py",
>>>>>>>>>>>>>>   File "/Users/dpage/git/pgadmin4/
>>>>>>>>>>>>>> web/pgadmin/feature_tests/pg_utilities_backup_restore_test.py",
>>>>>>>>>>>>>> line 93, in runTest
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>   File "/Users/dpage/git/pgadmin4/
>>>>>>>>>>>>>> web/regression/feature_utils/pgadmin_page.py", line 211, in
>>>>>>>>>>>>>> fill_input_by_field_name
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>   File "/Users/dpage/git/pgadmin4/
>>>>>>>>>>>>>> web/regression/feature_utils/pgadmin_page.py", line 251, in
>>>>>>>>>>>>>>   File "/Users/dpage/git/pgadmin4/
>>>>>>>>>>>>>> web/regression/feature_utils/pgadmin_page.py", line 337, in
>>>>>>>>>>>>>> _wait_for
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>   File "/Users/dpage/.virtualenvs/
>>>>>>>>>>>>>> pgadmin4/lib/python2.7/site-packages/selenium/webdriver/support/wait.py",
>>>>>>>>>>>>>> line 80, in until
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> We passed the tests through our CI the feature tests are
>>>>>>>>>>>>>>>> not passing, but the linter fails:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> and we do not have coverage for it: https://redmine.

---

From: Khushboo Vashi <[email-masked]>
Date: Wed, 6 Jun 2018 10:42:38 +0530

Hi Dave,

As per our discussion I have added the code to clean up the generated files.
Please find the attached updated patch.

Thanks,
Khushboo

On Wed, Jun 6, 2018 at 9:37 AM, Khushboo Vashi <
[email-masked]> wrote:

>>>>>>>>>>>>>> On Wed, May 30, 2018 at 1:05 AM, Dave Page <[email-masked]
>>>>>>>>>>>>>> > wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Hi
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> please find the attached updated patch for the test cases
>>>>>>>>>>>>>>>> of Backup, Restore and Maintenance modules which includes:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> 1. Unit test cases
>>>>>>>>>>>>>>> 1) DEFAULT_BINARY_PATHS should be default_binary_paths in
>>>>>>>>>>>>>>> the JSON config file.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Will do.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> /pgadmin/feature_tests/pg_utilities_maintenance_test.py",
>>>>>>>>>>>>>>> line 56, in runTest
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> /pgadmin/feature_tests/pg_utilities_maintenance_test.py",
>>>>>>>>>>>>>>> I have ran the feature tests with multiple servers many
>>>>>>>>>>>>>> times but didn't get a single failure.
>>>>>>>>>>>>>>>>> - Looks like there is a bug report in this area of the
>>>>>>>>>>>>>>>>> code and we do not have coverage for it:
>>>>>>>>>>>>>>>>> The configuration change, maybe need to be updated. When
>>>>>>>>>>>>>>>>> we install multiple versions of postgres the binaries live in
>>>>>>>>>>>>>>>>>> Please find the attached patch which covers test cases
>>>>>>>>>>>>>>>>>> for the backup module (RM #3206).
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> 1. Unit test cases

---

From: Khushboo Vashi <[email-masked]>
Date: Wed, 6 Jun 2018 12:27:19 +0530

Please find the atatched patch with the PEP8 fixes.

On Wed, Jun 6, 2018 at 10:42 AM, Khushboo Vashi <
[email-masked]> wrote:

>>>>>>>>> Can you send me the test_config.json file?  The above code sets
>>>>>>>> the paths to the SQLite database and through the logs couldn't figure out
>>>>>>>> the exact failure.
>>>>>>>>
>>>>>>>
>>>>>>> Without this code, the test cases should work as I already set
>>>>>> paths through below code.
>>>>>>
>>>>>>>>>>>>>>>> dmin4/lib/python2.7/site-packa
>>>>>>>>>>>>>>>> dmin4/lib/python2.7/site-packa
>>>>>>>>>>>>>>>> dmin4/lib/python2.7/site-packa
>>>>>>>>>>>>>>>> dmin4/lib/python2.7/site-packa
>>>>>>>>>>>>>>>> ges/selenium/webdriver/remote/errorhandler.py", line 242,
>>>>>>>>>>>>>>>> in check_response
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> dmin4/lib/python2.7/site-packa
>>>>>>>>>>>>>>>>>> We reviewed the patch and it is very nice to see some
>>>>>>>>>>>>>>>>>> more coverage in this area. Good job :D
>>>>>>>>>>>>>>>>>>

---

From: Khushboo Vashi <[email-masked]>
Date: Wed, 6 Jun 2018 15:54:26 +0530

On Wed, Jun 6, 2018 at 2:30 PM, Dave Page <[email-masked]> wrote:

> Hi
>
> I'm seeing various failures with this patch. Many of them appear to be
> being caused by the notification popups obscuring elements. Perhaps they
> need to be explicitly closed? Errors below, screenshots attached.
>
Notifications should be taken care by test cases. On my MAC and Linux these
are working fine.
I will check with someone else's machine.

> utilities_backup_restore_test.py", line 97, in runTest
>     self.page.find_by_xpath("//div[contains(@class,'wcFloatingFocus')"
> line 171, in find_by_xpath
>     lambda driver: driver.find_element_by_xpath(xpath)
> line 263, in wait_for_element
>     return self._wait_for("element to exist", element_if_it_exists)
> TimeoutException: Message: Timed out waiting for element to exist
>
>
> ERROR: runTest (pgadmin.feature_tests.xss_checks_file_manager_test.
> CheckFileManagerFeatureTest)
> Tests to check if File manager is vulnerable to XSS
>   File "/Users/dpage/git/pgadmin4/web/regression/feature_utils/base_feature_test.py",
> line 66, in tearDown
>     self.after()
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_checks_file_manager_test.py",
> line 46, in after
>     self.page.close_query_tool('sql', False)
> line 104, in close_query_tool
>     "//li[contains(@class, 'context-menu-item')]/span[contains(text(),"
> line 171, in find_by_xpath
>     lambda driver: driver.find_element_by_xpath(xpath)
> line 263, in wait_for_element
>     return self._wait_for("element to exist", element_if_it_exists)
> TimeoutException: Message: Timed out waiting for element to exist
>
>
> ERROR: runTest (pgadmin.feature_tests.xss_checks_panels_and_query_tool_
> test.CheckForXssFeatureTest)
> Test XSS check for panels and query tool
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_
> checks_panels_and_query_tool_test.py", line 57, in runTest
>     self.page.add_server(self.server)
> line 65, in add_server
>     self.find_by_xpath("//button[contains(.,'Save')]").click()
> WebDriverException: Message: unknown error: Element <button type="save"
> class="btn btn-primary" title="Save this object.">...</button> is not
> clickable at point (661, 761). Other element would receive the click: <div
> class="pg-bg-etime">...</div>
> ERROR: runTest (pgadmin.feature_tests.xss_checks_panels_and_query_tool_
> test.CheckForXssFeatureTest)
> Test XSS check for panels and query tool
>   File "/Users/dpage/git/pgadmin4/web/regression/feature_utils/base_feature_test.py",
> line 66, in tearDown
>     self.after()
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_
> checks_panels_and_query_tool_test.py", line 69, in after
>     self.page.remove_server(self.server)
> line 124, in remove_server
>     "' and @class='aciTreeItem']")
> line 171, in find_by_xpath
>     lambda driver: driver.find_element_by_xpath(xpath)
> line 263, in wait_for_element
>     return self._wait_for("element to exist", element_if_it_exists)
> TimeoutException: Message: Timed out waiting for element to exist
>
>
> ERROR: runTest (pgadmin.feature_tests.xss_checks_pgadmin_debugger_test.
> CheckDebuggerForXssFeatureTest)
> Tests to check if Debugger is vulnerable to XSS
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_
> checks_pgadmin_debugger_test.py", line 41, in runTest
>     self.page.add_server(self.server)
> line 65, in add_server
>     self.find_by_xpath("//button[contains(.,'Save')]").click()
> WebDriverException: Message: unknown error: Element <button type="save"
> class="btn btn-primary" title="Save this object.">...</button> is not
> clickable at point (661, 761). Other element would receive the click: <div
> class="pg-bg-etime">...</div>
> ERROR: runTest (pgadmin.feature_tests.xss_checks_pgadmin_debugger_test.
> CheckDebuggerForXssFeatureTest)
> Tests to check if Debugger is vulnerable to XSS
>   File "/Users/dpage/git/pgadmin4/web/regression/feature_utils/base_feature_test.py",
> line 66, in tearDown
>     self.after()
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_
> checks_pgadmin_debugger_test.py", line 46, in after
>     self.page.remove_server(self.server)
> line 124, in remove_server
>     "' and @class='aciTreeItem']")
> line 171, in find_by_xpath
>     lambda driver: driver.find_element_by_xpath(xpath)
> line 263, in wait_for_element
>     return self._wait_for("element to exist", element_if_it_exists)
> TimeoutException: Message: Timed out waiting for element to exist
>
>
> ERROR: runTest (pgadmin.feature_tests.xss_checks_roles_control_test.
> CheckRoleMembershipControlFeatureTest)
> Tests to check if Role membership control is vulnerable to XSS
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_checks_roles_control_test.py",
> line 37, in runTest
>     self.page.add_server(self.server)
> line 65, in add_server
>     self.find_by_xpath("//button[contains(.,'Save')]").click()
> WebDriverException: Message: unknown error: Element <button type="save"
> class="btn btn-primary" title="Save this object.">...</button> is not
> clickable at point (661, 761). Other element would receive the click: <div
> class="pg-bg-etime">...</div>
> ERROR: runTest (pgadmin.feature_tests.xss_checks_roles_control_test.
> CheckRoleMembershipControlFeatureTest)
> Tests to check if Role membership control is vulnerable to XSS
>   File "/Users/dpage/git/pgadmin4/web/regression/feature_utils/base_feature_test.py",
> line 66, in tearDown
>     self.after()
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_checks_roles_control_test.py",
> line 42, in after
>     self.page.remove_server(self.server)
> line 124, in remove_server
>     "' and @class='aciTreeItem']")
> line 171, in find_by_xpath
>     lambda driver: driver.find_element_by_xpath(xpath)
> line 263, in wait_for_element
>     return self._wait_for("element to exist", element_if_it_exists)
> TimeoutException: Message: Timed out waiting for element to exist
>
>
> FAIL: runTest (pgadmin.feature_tests.pg_utilities_maintenance_test.
> Test for PG maintenance: database pg_maintenance
> utilities_maintenance_test.py", line 63, in runTest
>     self._verify_command()
> utilities_maintenance_test.py", line 90, in _verify_command
>     self.assertEquals(command, "VACUUM "
> AssertionError: u'Backing up an object on the server \'Regression - PG 9.4
> Feature Tests (localhost:5432)\' from database \'pg_utility_test_db\'...\nRunning
> command:\n/Library/PostgreSQL/9.4/bin/pg_dump --file
> "/Users/dpage/test_backup" --host "localhost" --port "5432" --username
> "postgres" --no-password --verbose --format=c --blobs "pg_utility_test_db"'
> != 'VACUUM (VERBOSE)\nRunning Query:\nVACUUM VERBOSE;'
>
> FAIL: runTest (pgadmin.feature_tests.pg_utilities_maintenance_test.
> utilities_maintenance_test.py", line 63, in runTest
>     self._verify_command()
> utilities_maintenance_test.py", line 97, in _verify_command
>     " public." + self.table_name + ";")
> AssertionError: u'Backing up an object on the server \'Regression - PG 9.4
> Feature Tests (localhost:5432)\' from database \'pg_utility_test_db\'...\nRunning
> command:\n/Library/PostgreSQL/9.4/bin/pg_dump --file
> "/Users/dpage/test_backup" --host "localhost" --port "5432" --username
> "postgres" --no-password --verbose --format=c --blobs "pg_utility_test_db"'
> != 'VACUUM (VERBOSE)\nRunning Query:\nVACUUM VERBOSE
> public.pg_maintenance_table;'
>
> FAIL: runTest (pgadmin.tools.maintenance.tests.test_create_maintenance_
> job.MaintenanceJobTest)
> When maintenance the object with the default options
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/maintenance/
> tests/test_create_maintenance_job.py", line 85, in runTest
>     self.assertIn(self.expected_cmd, process_list[0]['details'])
> AssertionError: 'VACUUM VERBOSE' not found in u'<div class="h5">Backing up
> an object on the server \'Regression - PG 9.4 Feature Tests
> (localhost:5432)\' from database \'pg_utility_test_db\'...</div><div
> class="h5">Running command:</b><br><span class="pg-bg-cmd
> enable-selection">/Library/PostgreSQL/9.4/bin/pg_dump --file
> "/Users/dpage/test_backup" --host "localhost" --port "5432" --username
> "postgres" --no-password --verbose --format=c --blobs
> "pg_utility_test_db"</span></div>'
>
> Ran 369 tests in 493.707s
>
> FAILED (failures=3, errors=8, skipped=21)
>
>
>
> On Wed, Jun 6, 2018 at 7:57 AM, Khushboo Vashi <
>>>>>>>>> It seems clear from the code shown that it's not setting the
>>>>>>>>> binary paths for gpdb database servers. Shouldn't it be something like:
>>>>>>>>>
>>>>>>> My bad. Removed this code and also updated set_preference function
>>>>>> for greenplum database.
>>>>>>>>>> test_backup_utils.py file name is misleading, these are not
>>>>>>>>>>> tests, are helpers.
>>>>>>>>>>> ​
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Thanks
>>>>>>>>>>> Victoria & Joao
>>>>>>>>>>>
>>>>>>>>>>>>>>> We've been noticing some issues with the tests on both our
>>>>>>>>>>>>>>> CI and local Mac workstations.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>    plenty of app.context() issues. It must not be valid
>>>>>>>>>>>>>>>    when running tests.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> ​
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> please find the attached updated patch for the test
>>>>>>>>>>>>>>>>>>> cases of Backup, Restore and Maintenance modules which includes:
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> 1. Unit test cases
>>>>>>>>>>>>>>>>>> ges/selenium/webdriver/remote/errorhandler.py", line
>>>>>>>>>>>>>>>>>> 242, in check_response
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> On Wed, Apr 25, 2018 at 9:40 PM, Joao De Almeida Pereira
>>>>>>>>>>>>>>>>>>> <[email-masked]> wrote:
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> Hi Khushboo,
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> We passed the tests through our CI the feature tests
>>>>>>>>>>>>>>>>>>>> are not passing, but the linter fails:
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>   Looks like in some of the unit tests we only have
>>>>>>>>>>>>>>>>>>>> happy path tests, maybe we should see if there are any sad paths that also
>>>>>>>>>>>>>>>>>>>> need coverage.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> The configuration change, maybe need to be updated.
>>>>>>>>>>>>>>>>>>>> When we install multiple versions of postgres the binaries live in
>>>>>>>>>>>>>>>>>>>> `/usr/lib/postgresql/{{db_version}}/bin`, which makes
>>>>>>>>>>>>>>>>>>>> us think that this configuration should live near the server configuration,

---

From: Khushboo Vashi <[email-masked]>
Date: Fri, 8 Jun 2018 11:03:24 +0530

Hi Dave,

As per our discussion I have changed the window size to 1280X800, before it
was 1280X900.
Please find the attached updated patch.

Thanks,
Khushboo

On Wed, Jun 6, 2018 at 3:54 PM, Khushboo Vashi <
[email-masked]> wrote:

> Notifications should be taken care by test cases. On my MAC and Linux
> these are working fine.
>> line 97, in runTest
>> ERROR: runTest (pgadmin.feature_tests.xss_che
>> cks_file_manager_test.CheckFileManagerFeatureTest)
>> ERROR: runTest (pgadmin.feature_tests.xss_che
>> cks_panels_and_query_tool_test.CheckForXssFeatureTest)
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_che
>> cks_panels_and_query_tool_test.py", line 57, in runTest
>> ERROR: runTest (pgadmin.feature_tests.xss_che
>> cks_panels_and_query_tool_test.CheckForXssFeatureTest)
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_che
>> cks_panels_and_query_tool_test.py", line 69, in after
>> ERROR: runTest (pgadmin.feature_tests.xss_che
>> cks_pgadmin_debugger_test.CheckDebuggerForXssFeatureTest)
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py",
>> line 41, in runTest
>> ERROR: runTest (pgadmin.feature_tests.xss_che
>> cks_pgadmin_debugger_test.CheckDebuggerForXssFeatureTest)
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py",
>> line 46, in after
>> ERROR: runTest (pgadmin.feature_tests.xss_che
>> cks_roles_control_test.CheckRoleMembershipControlFeatureTest)
>> ERROR: runTest (pgadmin.feature_tests.xss_che
>> cks_roles_control_test.CheckRoleMembershipControlFeatureTest)
>> FAIL: runTest (pgadmin.feature_tests.pg_util
>> line 63, in runTest
>> line 90, in _verify_command
>> AssertionError: u'Backing up an object on the server \'Regression - PG
>> 9.4 Feature Tests (localhost:5432)\' from database
>> \'pg_utility_test_db\'...\nRunning command:\n/Library/PostgreSQL/9.4/bin/pg_dump
>> --file "/Users/dpage/test_backup" --host "localhost" --port "5432"
>> --username "postgres" --no-password --verbose --format=c --blobs
>> "pg_utility_test_db"' != 'VACUUM (VERBOSE)\nRunning Query:\nVACUUM VERBOSE;'
>>
>> FAIL: runTest (pgadmin.feature_tests.pg_util
>> line 63, in runTest
>> line 97, in _verify_command
>> AssertionError: u'Backing up an object on the server \'Regression - PG
>> 9.4 Feature Tests (localhost:5432)\' from database
>> \'pg_utility_test_db\'...\nRunning command:\n/Library/PostgreSQL/9.4/bin/pg_dump
>> --file "/Users/dpage/test_backup" --host "localhost" --port "5432"
>> --username "postgres" --no-password --verbose --format=c --blobs
>> "pg_utility_test_db"' != 'VACUUM (VERBOSE)\nRunning Query:\nVACUUM VERBOSE
>> FAIL: runTest (pgadmin.tools.maintenance.tes
>> ts.test_create_maintenance_job.MaintenanceJobTest)
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/maintenance/tes
>> ts/test_create_maintenance_job.py", line 85, in runTest
>> AssertionError: 'VACUUM VERBOSE' not found in u'<div class="h5">Backing
>> up an object on the server \'Regression - PG 9.4 Feature Tests
>>>>>>>>>>>>>>>>>>> 1) DEFAULT_BINARY_PATHS should be default_binary_paths
>>>>>>>>>>>>>>>>>>> in the JSON config file.
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> Will do.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> WebDriverException: Message: unknown error: Element
>>>>>>>>>>>>>>>>>>> <span class="aciTreeItem">...</span> is not clickable at point (223, 604).
>>>>>>>>>>>>>>>>>>> Other element would receive the click: <div class="wcFrameCenter
>>>>>>>>>>>>>>>>>>> /regression/feature_utils/pgadmin_page.py", line 211,
>>>>>>>>>>>>>>>>>>> in fill_input_by_field_name
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> /regression/feature_utils/pgadmin_page.py", line 251,
>>>>>>>>>>>>>>>>>>> in wait_for_input_field_content
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> TimeoutException: Message: Timed out waiting for field
>>>>>>>>>>>>>>>>>>> to contain 'test_backup_file'
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> On Wed, Apr 25, 2018 at 9:40 PM, Joao De Almeida
>>>>>>>>>>>>>>>>>>>> Pereira <[email-masked]> wrote:
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> Hi Khushboo,
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> For the feature tests, we realized we had to update
>>>>>>>>>>>>>>>>>>>>> the configuration, and we did that, but we get the following error
>>>>>>>>>>>>>>>>>>>>> attached. We spent some time trying to understand the problem but we were
>>>>>>>>>>>>>>>>>>>>> not successful.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> Codewise:
>>>>>>>>>>>>>>>>>>>>>> Please find the attached patch which covers test
>>>>>>>>>>>>>>>>>>>>>> cases for the backup module (RM #3206).
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> 1. Unit test cases

---

From: Dave Page <[email-masked]>
Date: Fri, 8 Jun 2018 10:08:42 +0100

Hi

On Fri, Jun 8, 2018 at 6:33 AM, Khushboo Vashi <
[email-masked]> wrote:

> Hi Dave,
>
> As per our discussion I have changed the window size to 1280X800, before
> it was 1280X900.
> Please find the attached updated patch
>

I'm not sure that actually made any difference on my system. The window
continued to look taller than it is wide, so I wonder if the code to set
the size is being ignored, or is at the wrong place?

Anyway, I got 10 failures with this patch :-(

ERROR: runTest

  File

  File

  File

  File

  File

ERROR: runTest
(pgadmin.feature_tests.xss_checks_pgadmin_debugger_test.CheckDebuggerForXssFeatureTest)

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py",
line 42, in runTest

    self._function_node_expandable()

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/feature_tests/xss_checks_pgadmin_debugger_test.py",
line 57, in _function_node_expandable

    self.page.select_tree_item("a_test_function()")

  File
"/Users/dpage/git/pgadmin4/web/regression/feature_utils/pgadmin_page.py",
line 135, in select_tree_item

    "' and @class='aciTreeItem']").click()

  File

  File

  File

  File

ERROR: runTest
(pgadmin.tools.backup.tests.test_create_backup_job.BackupJobTest)

When backup the object with the default options

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/tests/test_create_backup_job.py",
line 58, in runTest

    self.assertNotIn

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/tests/test_backup_utils.py",
line 33, in run_backup_job

    random.randint(1, 9999999)))

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
line 830, in get

    return self.open(*args, **kw)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/testing.py",
line 127, in open

    follow_redirects=follow_redirects)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
line 803, in open

    response = self.run_wsgi_app(environ, buffered=buffered)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
line 716, in run_wsgi_app

    rv = run_wsgi_app(self.application, environ, buffered=buffered)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
line 923, in run_wsgi_app

    app_rv = app(environ, start_response)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1997, in __call__

    return self.wsgi_app(environ, start_response)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1985, in wsgi_app

    response = self.handle_exception(e)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1540, in handle_exception

    reraise(exc_type, exc_value, tb)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1982, in wsgi_app

    response = self.full_dispatch_request()

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1614, in full_dispatch_request

    rv = self.handle_user_exception(e)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1517, in handle_user_exception

    reraise(exc_type, exc_value, tb)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1612, in full_dispatch_request

    rv = self.dispatch_request()

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1598, in dispatch_request

    return self.view_functions[rule.endpoint](**req.view_args)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask_login.py",
line 792, in decorated_view

    return func(*args, **kwargs)

  File "/Users/dpage/git/pgadmin4/web/pgadmin/misc/bgprocess/__init__.py",
line 62, in index

    return make_response(response=BatchProcess.list())

  File "/Users/dpage/git/pgadmin4/web/pgadmin/misc/bgprocess/processes.py",
line 584, in list

    details = desc.details(p.command, args)

  File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/__init__.py",
line 159, in details

    name, host, port = self.get_server_details()

  File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/__init__.py",
line 122, in get_server_details

AttributeError: 'NoneType' object has no attribute 'use_ssh_tunnel'

ERROR: runTest
(pgadmin.tools.maintenance.tests.test_create_maintenance_job.MaintenanceJobTest)

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/tools/maintenance/tests/test_create_maintenance_job.py",
line 71, in runTest

    random.randint(1, 9999999)))

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
line 830, in get

    return self.open(*args, **kw)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/testing.py",
line 127, in open

    follow_redirects=follow_redirects)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
line 803, in open

    response = self.run_wsgi_app(environ, buffered=buffered)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
line 716, in run_wsgi_app

    rv = run_wsgi_app(self.application, environ, buffered=buffered)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
line 923, in run_wsgi_app

    app_rv = app(environ, start_response)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1997, in __call__

    return self.wsgi_app(environ, start_response)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1985, in wsgi_app

    response = self.handle_exception(e)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1540, in handle_exception

    reraise(exc_type, exc_value, tb)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1982, in wsgi_app

    response = self.full_dispatch_request()

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1614, in full_dispatch_request

    rv = self.handle_user_exception(e)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1517, in handle_user_exception

    reraise(exc_type, exc_value, tb)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1612, in full_dispatch_request

    rv = self.dispatch_request()

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1598, in dispatch_request

    return self.view_functions[rule.endpoint](**req.view_args)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask_login.py",
line 792, in decorated_view

    return func(*args, **kwargs)

  File "/Users/dpage/git/pgadmin4/web/pgadmin/misc/bgprocess/__init__.py",
line 62, in index

    return make_response(response=BatchProcess.list())

  File "/Users/dpage/git/pgadmin4/web/pgadmin/misc/bgprocess/processes.py",
line 584, in list

    details = desc.details(p.command, args)

  File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/__init__.py",
line 159, in details

    name, host, port = self.get_server_details()

  File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/__init__.py",
line 122, in get_server_details

AttributeError: 'NoneType' object has no attribute 'use_ssh_tunnel'

ERROR: runTest
(pgadmin.tools.restore.tests.test_create_restore_job.RestoreJobTest)

When restore the object with the default options

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/tools/restore/tests/test_create_restore_job.py",
line 95, in runTest

    self.create_backup()

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/tools/restore/tests/test_create_restore_job.py",
line 86, in create_backup

    self.assertNotIn

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/tests/test_backup_utils.py",
line 33, in run_backup_job

    random.randint(1, 9999999)))

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
line 830, in get

    return self.open(*args, **kw)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/testing.py",
line 127, in open

    follow_redirects=follow_redirects)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
line 803, in open

    response = self.run_wsgi_app(environ, buffered=buffered)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
line 716, in run_wsgi_app

    rv = run_wsgi_app(self.application, environ, buffered=buffered)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
line 923, in run_wsgi_app

    app_rv = app(environ, start_response)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1997, in __call__

    return self.wsgi_app(environ, start_response)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1985, in wsgi_app

    response = self.handle_exception(e)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1540, in handle_exception

    reraise(exc_type, exc_value, tb)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1982, in wsgi_app

    response = self.full_dispatch_request()

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1614, in full_dispatch_request

    rv = self.handle_user_exception(e)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1517, in handle_user_exception

    reraise(exc_type, exc_value, tb)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1612, in full_dispatch_request

    rv = self.dispatch_request()

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1598, in dispatch_request

    return self.view_functions[rule.endpoint](**req.view_args)

  File
"/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask_login.py",
line 792, in decorated_view

    return func(*args, **kwargs)

  File "/Users/dpage/git/pgadmin4/web/pgadmin/misc/bgprocess/__init__.py",
line 62, in index

    return make_response(response=BatchProcess.list())

  File "/Users/dpage/git/pgadmin4/web/pgadmin/misc/bgprocess/processes.py",
line 584, in list

    details = desc.details(p.command, args)

  File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/__init__.py",
line 159, in details

    name, host, port = self.get_server_details()

  File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/__init__.py",
line 122, in get_server_details

AttributeError: 'NoneType' object has no attribute 'use_ssh_tunnel'

FAIL: runTest
(pgadmin.browser.server_groups.servers.databases.schemas.functions.tests.test_trigger_func_add.TriggerFuncAddTestCase)

Fetch Trigger Function Node URL

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/test_trigger_func_add.py",
line 111, in runTest

AssertionError: 500 != 200

FAIL: runTest
(pgadmin.browser.server_groups.servers.databases.schemas.functions.tests.test_trigger_func_delete.TriggerFuncDeleteTestCase)

Fetch Trigger Function Node URL

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/test_trigger_func_delete.py",
line 72, in runTest

AssertionError: 500 != 200

FAIL: runTest
(pgadmin.browser.server_groups.servers.databases.schemas.functions.tests.test_trigger_func_get.TriggerFuncGetTestCase)

Fetch Trigger Function Node URL

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/test_trigger_func_get.py",
line 72, in runTest

AssertionError: 500 != 200

FAIL: runTest
(pgadmin.browser.server_groups.servers.databases.schemas.functions.tests.test_trigger_func_put.TriggerFuncPutTestCase)

Fetch Trigger Function Node URL

  File
"/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/test_trigger_func_put.py",
line 87, in runTest

    self.assertEquals(put_response.status_code, 200)

AssertionError: 500 != 200

FAIL: runTest

  File

    self._verify_command()

  File

AssertionError: u'Backing up an object on the server \'Regression - PG 11
Feature Tests (localhost:5436)\' from database
\'pg_utility_test_db\'...\nRunning
command:\n/Library/PostgreSQL/11/bin/pg_dump --file
"/Users/dpage/test_backup" --host "localhost" --port "5436" --username
"postgres" --no-password --verbose --format=c --blobs "pg_utility_test_db"'
!= 'VACUUM (VERBOSE)\nRunning Query:\nVACUUM VERBOSE;'

FAIL: runTest

  File

    self._verify_command()

  File

AssertionError: u'Backing up an object on the server \'Regression - PG 11
Feature Tests (localhost:5436)\' from database
\'pg_utility_test_db\'...\nRunning
command:\n/Library/PostgreSQL/11/bin/pg_dump --file
"/Users/dpage/test_backup" --host "localhost" --port "5436" --username
"postgres" --no-password --verbose --format=c --blobs "pg_utility_test_db"'
!= 'VACUUM (VERBOSE)\nRunning Query:\nVACUUM VERBOSE
public.pg_maintenance_table;'

Ran 369 tests in 417.660s

FAILED (failures=6, errors=5, skipped=13)

Test Result Summary

Regression - PG 11:

346 tests passed

10 tests failed:

TriggerFuncGetTestCase (Fetch Trigger Function Node URL)

MaintenanceJobTest (When maintenance the object with the default options)

TriggerFuncDeleteTestCase (Fetch Trigger Function Node URL)

TriggerFuncPutTestCase (Fetch Trigger Function Node URL)

RestoreJobTest (When restore the object with the default options)

CheckDebuggerForXssFeatureTest (Tests to check if Debugger is vulnerable to
XSS)

TriggerFuncAddTestCase (Fetch Trigger Function Node URL)

PGUtilitiesBackupFeatureTest (Test for PG utilities - Backup and Restore)

PGUtilitiesMaintenanceFeatureTest (Test for PG maintenance: database,

Test for PG maintenance: database pg_maintenance)

BackupJobTest (When backup the object with the default options)

13 tests skipped:

SynonymDeleteTestCase (Fetch synonym Node URL)

SynonymGetTestCase (Fetch synonym Node URL)

PackageDeleteTestCase (Fetch Package Node URL)

ResourceGroupsGetTestCase (Get resource groups)

TestSSLConnection (Test for SSL connection)

ResourceGroupsAddTestCase (Add resource groups)

PackagePutTestCase (Fetch Package Node URL)

SynonymPutTestCase (Fetch synonym Node URL)

ResourceGroupsPutTestCase (Put resource groups)

ResourceGroupsDeleteTestCase (Delete resource groups)

SynonymAddTestCase (Default Node URL)

PackageAddTestCase (Fetch Package Node URL)

PackageGetTestCase (Fetch Package Node URL)

---

From: Khushboo Vashi <[email-masked]>
Date: Tue, 12 Jun 2018 15:54:53 +0530

Hi,

Please find the attached patch excluding feature test cases.
Python test cases are working fine, so we can commit this patch. I am
working on fixing the feature tests which are failing on the different
window sizes.

Thanks,
Khushboo

On Fri, Jun 8, 2018 at 2:38 PM, Dave Page <[email-masked]> wrote:

> ERROR: runTest (pgadmin.tools.backup.tests.te
> st_create_backup_job.BackupJobTest)
>
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/tests/test_create_backup_job.py",
> line 58, in runTest
>
>     self.assertNotIn
>
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/tests/test_backup_utils.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
> line 830, in get
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/testing.py",
> line 127, in open
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
> line 803, in open
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1997, in __call__
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1985, in wsgi_app
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1982, in wsgi_app
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask_login.py",
> ERROR: runTest (pgadmin.tools.maintenance.tes
> ts/test_create_maintenance_job.py", line 71, in runTest
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
> line 830, in get
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/testing.py",
> line 127, in open
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
> line 803, in open
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1997, in __call__
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1985, in wsgi_app
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1982, in wsgi_app
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask_login.py",
> ERROR: runTest (pgadmin.tools.restore.tests.t
> est_create_restore_job.RestoreJobTest)
>
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/restore/tests/test_create_restore_job.py",
> line 95, in runTest
>
>     self.create_backup()
>
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/restore/tests/test_create_restore_job.py",
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/tests/test_backup_utils.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
> line 830, in get
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/testing.py",
> line 127, in open
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
> line 803, in open
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/werkzeug/test.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1997, in __call__
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1985, in wsgi_app
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1982, in wsgi_app
>
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask_login.py",
> FAIL: runTest (pgadmin.browser.server_groups.servers.databases.schemas.
> functions.tests.test_trigger_func_add.TriggerFuncAddTestCase)
>
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/databases/schemas/functions/tests/test_trigger_func_add.py",
> line 111, in runTest
>
> FAIL: runTest (pgadmin.browser.server_groups.servers.databases.schemas.
> functions.tests.test_trigger_func_delete.TriggerFuncDeleteTestCase)
>
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/databases/schemas/functions/tests/test_trigger_func_delete.py",
> line 72, in runTest
>
> FAIL: runTest (pgadmin.browser.server_groups.servers.databases.schemas.
> functions.tests.test_trigger_func_get.TriggerFuncGetTestCase)
>
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/databases/schemas/functions/tests/test_trigger_func_get.py",
> line 72, in runTest
>
> FAIL: runTest (pgadmin.browser.server_groups.servers.databases.schemas.
> functions.tests.test_trigger_func_put.TriggerFuncPutTestCase)
>
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/databases/schemas/functions/tests/test_trigger_func_put.py",
> line 87, in runTest
>
> FAIL: runTest (pgadmin.feature_tests.pg_utilities_maintenance_test.PGUtili
> tiesMaintenanceFeatureTest)
>
> \'pg_utility_test_db\'...\nRunning command:\n/Library/PostgreSQL/11/bin/pg_dump
> --file "/Users/dpage/test_backup" --host "localhost" --port "5436"
> FAIL: runTest (pgadmin.feature_tests.pg_utilities_maintenance_test.PGUtili
> tiesMaintenanceFeatureTest)
>
> \'pg_utility_test_db\'...\nRunning command:\n/Library/PostgreSQL/11/bin/pg_dump
> --file "/Users/dpage/test_backup" --host "localhost" --port "5436"
> CheckDebuggerForXssFeatureTest (Tests to check if Debugger is vulnerable
> to XSS)
>

---

From: Khushboo Vashi <[email-masked]>
Date: Tue, 12 Jun 2018 16:14:45 +0530

Please find the attached updated patch with some code cleanup.

On Tue, Jun 12, 2018 at 3:54 PM, Khushboo Vashi <
[email-masked]> wrote:

>> FAIL: runTest (pgadmin.browser.server_groups
>> .servers.databases.schemas.functions.tests.test_trigger_func
>> _add.TriggerFuncAddTestCase)
>>
>> FAIL: runTest (pgadmin.browser.server_groups
>> .servers.databases.schemas.functions.tests.test_trigger_func
>> _delete.TriggerFuncDeleteTestCase)
>>
>> FAIL: runTest (pgadmin.browser.server_groups
>> .servers.databases.schemas.functions.tests.test_trigger_func
>> _get.TriggerFuncGetTestCase)
>>
>> FAIL: runTest (pgadmin.browser.server_groups
>> .servers.databases.schemas.functions.tests.test_trigger_func
>> _put.TriggerFuncPutTestCase)
>>

---

From: Victoria Henry <[email-masked]>
Date: Tue, 12 Jun 2018 11:36:35 -0400

Hi Khushboo
can you explain a little bit more this while loop?

cnt = 0
while 1:
    if cnt > 1:
        break
    # Check the process list
    response1 = self.tester.get('/misc/bgprocess/?_='.format(
        random.randint(1, 9999999)))
    self.assertEquals(response1.status_code, 200)
    process_list = json.loads(response1.data.decode('utf-8'))

    if len(process_list) > 0 and 'execution_time' in process_list[0]:
        break
    time.sleep(0.5)
    cnt += 1

---

From: Khushboo Vashi <[email-masked]>
Date: Wed, 13 Jun 2018 17:42:09 +0530

Hi Victoria,

On Tue, Jun 12, 2018 at 9:06 PM, Victoria Henry <[email-masked]> wrote:

> From what it looks like this will only run twice, maybe a for would be a
> better solution because we know it will only run twice. Also are we sure we
> only want it to run twice?
>
> The code waits till the background process completes. So, while I
originally developed, not intended to run only twice.
But after that I put a kind of break point and that remains there. So, I
will remove that if condition which is not required.

> We are using PyCharm to do our developments and we notice there are a big
> group of unused variables throughout. We should remove them if they are not
> needed. Not sure if your editor also shows that information or not.
>
Do you know if there is a configuration in pycodestyle to enable the check
> for unused variables? That would help a lot.
>
> Thanks for sharing the information.

> The code
>
> assert 'execution_time' in process_list[0]
> assert 'stime' in process_list[0]
> assert 'exit_code' in process_list[0]
> assert process_list[0]['exit_code'] in self.expected_exit_code
>
> in test_Create_restore_job should use self.assertEqual or similar from
> unittest instead of plain assert. Because when something fails we do not
> have a way to understand what was wrong.
>
Will do.

> The tests on the restore are still failing GreenPlum.
>
It is failing because, Restore is not working with GreenPlum. Can you
please look into the Restore functionality for GPDB?

Thanks,
Khushboo

> ​
>
>
>
> Thanks
> Victoria & Joao
>
> On Tue, Jun 12, 2018 at 6:44 AM Khushboo Vashi <
>>>>> As per our discussion I have changed the window size to 1280X800,
>>>>> before it was 1280X900.
>>>> checks_pgadmin_debugger_test.py", line 42, in runTest
>>>>
>>>> checks_pgadmin_debugger_test.py", line 57, in _function_node_expandable
>>>>
>>>> ERROR: runTest (pgadmin.tools.backup.tests.test_create_backup_job.
>>>> BackupJobTest)
>>>>
>>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/backup/
>>>> tests/test_create_backup_job.py", line 58, in runTest
>>>>
>>>>     self.assertNotIn
>>>>
>>>> ERROR: runTest (pgadmin.tools.maintenance.
>>>> tests.test_create_maintenance_job.MaintenanceJobTest)
>>>>
>>>> tests/test_create_maintenance_job.py", line 71, in runTest
>>>>
>>>> ERROR: runTest (pgadmin.tools.restore.tests.test_create_restore_job.
>>>> RestoreJobTest)
>>>>
>>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/restore/
>>>> tests/test_create_restore_job.py", line 95, in runTest
>>>>
>>>>     self.create_backup()
>>>>
>>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/tools/restore/
>>>> tests/test_create_restore_job.py", line 86, in create_backup
>>>>
>>>>     self.assertNotIn
>>>>

---

From: Khushboo Vashi <[email-masked]>
Date: Fri, 15 Jun 2018 12:43:31 +0530

Hi,

> will remove that if condition which is not required.
I have made maximum 5 attempts.

>> Removed unused local variables.

>> have a way to understand what was wrong.
Done

Khushboo

>>>>> I'm not sure that actually made any difference on my system. The
>>>>> window continued to look taller than it is wide, so I wonder if the code to
>>>>> set the size is being ignored, or is at the wrong place?
>>>>>

---

From: Dave Page <[email-masked]>
Date: Fri, 15 Jun 2018 11:37:26 +0100

Thanks, applied with a few tweaks to remove some unused imports and a
couple of variables.

On Fri, Jun 15, 2018 at 8:13 AM, Khushboo Vashi <
[email-masked]> wrote:

>> Do you know if there is a configuration in pycodestyle to enable the
>>> check for unused variables? That would help a lot.
>>>
>>> unittest instead of plain assert. Because when something fails we do
>>> not have a way to understand what was wrong.
>>>
>> Will do.
>>
> Done
>