public inbox for [email protected]  
help / color / mirror / Atom feed
Fwd: pgAdmin IV : Unittest modular patch
29+ messages / 4 participants
[nested] [flat]

* Fwd: pgAdmin IV : Unittest modular patch
@ 2016-07-08 13:30  Navnath Gadakh <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-07-08 13:30 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,

PFA patch for modular API test cases.

Kindly, review the same and let me know for any modification.

-- 
*Thanks,*
*Navnath Gadakh*
*Software Engineer*
*Phone : + 91 9975389878*


*The Postgres Database Company*


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [text/x-patch] pgadmin_unittest_modular.patch (62.5K, 3-pgadmin_unittest_modular.patch)
  download | inline diff:
diff --git a/web/config.py b/web/config.py
index ff7c1db..6fb01ca 100644
--- a/web/config.py
+++ b/web/config.py
@@ -28,7 +28,10 @@ APP_REVISION = 0
 
 # Application version suffix, e.g. 'beta1', 'dev'. Usually an empty string
 # for GA releases.
-APP_SUFFIX = 'beta2.1'
+APP_SUFFIX = 'beta2'
+
+# Root path for pgadmin
+APP_ROOT = os.path.dirname(os.path.abspath(__file__))
 
 # Copyright string for display in the app
 APP_COPYRIGHT = 'Copyright 2013 - 2016, The pgAdmin Development Team'
@@ -154,6 +157,10 @@ MAX_SESSION_IDLE_TIME = 60
 # User account and settings storage
 ##########################################################################
 
+# The schema version number for the configuration database
+# DO NOT CHANGE UNLESS YOU ARE A PGADMIN DEVELOPER!!
+SETTINGS_SCHEMA_VERSION = 13
+
 # The default path to the SQLite database used to store user accounts and
 # settings. This default places the file in the same directory as this
 # config file, but generates an absolute path for use througout the app.
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/tests/__init__.py
new file mode 100644
index 0000000..aa01297
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/__init__.py
@@ -0,0 +1,15 @@
+# ##########################################################################
+#
+# #pgAdmin 4 - PostgreSQL Tools
+#
+# #Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# #This software is released under the PostgreSQL Licence
+#
+# ##########################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class DatabaseCreateTestCase(BaseTestGenerator):
+    def runTest(self):
+        return
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
new file mode 100644
index 0000000..4cb5092
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
@@ -0,0 +1,93 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+import uuid
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import advance_config_data
+
+
+class DatabaseAddTestCase(BaseTestGenerator):
+    """
+    This class will check server group node present on the object browser's
+    tree node by response code.
+    """
+
+    scenarios = [
+        # Fetching default URL for database node.
+        ('Check Databases Node URL', dict(url='/browser/database/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function perform the two tasks
+         1. Login to test client
+         2. Add the test server
+
+        :return: None
+        """
+
+        utils.login_tester_account(self.tester)
+        # Add the server
+        utils.add_server(self.tester)
+
+    def runTest(self):
+        """ This function will add database under 1st server of tree node. """
+
+        server_connect_response, server_group, server_id = \
+            utils.connect_server(self.tester)
+
+        if server_connect_response['data']['connected']:
+            data = {
+                "datacl": advance_config_data['test_add_database_data'][0]
+                ['test_privileges_acl'],
+                "datconnlimit": advance_config_data
+                ['test_add_database_data'][0]['test_conn_limit'],
+                "datowner": advance_config_data
+                ['test_add_database_data'][0]['test_owner'],
+                "deffuncacl": advance_config_data
+                ['test_add_database_data'][0]['test_fun_acl'],
+                "defseqacl": advance_config_data
+                ['test_add_database_data'][0]['test_seq_acl'],
+                "deftblacl": advance_config_data
+                ['test_add_database_data'][0]['test_tbl_acl'],
+                "deftypeacl": advance_config_data
+                ['test_add_database_data'][0]['test_type_acl'],
+                "encoding": advance_config_data
+                ['test_add_database_data'][0]['test_encoding'],
+                "name": str(uuid.uuid4())[1:8],
+                "privileges": advance_config_data
+                ['test_add_database_data'][0]['test_privileges'],
+                "securities": advance_config_data
+                ['test_add_database_data'][0]['test_securities'],
+                "variables": advance_config_data
+                ['test_add_database_data'][0]['test_variables']
+            }
+
+            db_response = self.tester.post(self.url + str(server_group) + "/"
+                                           + server_id + "/",
+                                           data=json.dumps(data),
+                                           content_type='html/json')
+            self.assertTrue(db_response.status_code, 200)
+            response_data = json.loads(db_response.data.decode())
+            utils.write_db_parent_id(response_data)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
+
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
new file mode 100644
index 0000000..f21905b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
@@ -0,0 +1,70 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import config_data
+from regression.test_nodes import test_getnodes
+from regression.test_utils import get_ids
+
+
+class DatabaseDeleteTestCase(BaseTestGenerator):
+    """ This class will delete the database under last added server. """
+
+    scenarios = [
+        # Fetching default URL for database node.
+        ('Check Databases Node URL', dict(url='/browser/database/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function perform the three tasks
+         1. Login to test client
+         2. Add the test server
+         3. Connect to server
+
+        :return: None
+        """
+
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
+        # Secondly, connect to server/database
+        utils.connect_server(self.tester)
+
+    def runTest(self):
+        """ This function will delete the database."""
+
+        all_id = get_ids()
+        server_id = all_id["sid"][0]
+        db_id = all_id["did"][0]
+        srv_grp = config_data['test_server_group']
+        db_con = test_getnodes(node=self)
+        if len(db_con) == 0:
+            raise Exception("No database(s) to delete!!!")
+        response = self.tester.delete(self.url + str(srv_grp) + '/' +
+                                      str(server_id) + '/' + str(db_id),
+                                      follow_redirects=True)
+
+        response_data = json.loads(response.data.decode())
+        self.assertTrue(response_data['success'], 1)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
+
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
new file mode 100644
index 0000000..e07fbba
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
@@ -0,0 +1,67 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import config_data
+from regression.test_nodes import test_getnodes
+from regression.test_utils import get_ids
+
+
+class DatabasesGetTestCase(BaseTestGenerator):
+    """
+    This class will fetch database added under last added server.
+    """
+
+    scenarios = [
+        # Fetching default URL for database node.
+        ('Check Databases Node URL', dict(url='/browser/database/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function perform the three tasks
+         1. Login to test client
+         2. Add the test server
+         3. Connect to server
+
+        :return: None
+        """
+
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
+        # Secondly, connect to server/database
+        utils.connect_server(self.tester)
+
+    def runTest(self):
+        """ This function will fetch added database. """
+
+        all_id = get_ids()
+        server_id = all_id["sid"][0]
+        db_id = all_id["did"][0]
+        srv_grp = config_data['test_server_group']
+
+        db_con = test_getnodes(node=self)
+        if db_con["info"] == "Database connected.":
+            response = self.tester.get(self.url + str(srv_grp) + '/' +
+                                       str(server_id) + '/' + str(db_id),
+                                       follow_redirects=True)
+            self.assertEquals(response.status_code, 200)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
new file mode 100644
index 0000000..5d36400
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
@@ -0,0 +1,76 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import config_data, advance_config_data
+from regression.test_nodes import test_getnodes
+from regression.test_utils import get_ids
+
+
+class DatabasesUpdateTestCase(BaseTestGenerator):
+    """
+    This class will update the database under last added server.
+    """
+
+    scenarios = [
+        # Fetching default URL for database node.
+        ('Check Databases Node', dict(url='/browser/database/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function perform the three tasks
+         1. Login to test client
+         2. Add the test server
+         3. Connect to server
+
+        :return: None
+        """
+
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
+        # Secondly, connect to server/database
+        utils.connect_server(self.tester)
+
+    def runTest(self):
+        """ This function will update the comments field of database."""
+
+        all_id = get_ids()
+        server_id = all_id["sid"][0]
+        db_id = all_id["did"][0]
+        test_getnodes(node=self)
+        srv_grp = config_data['test_server_group']
+
+        data = {
+            "comments": advance_config_data["test_db_update_data"][0]
+            ["test_comment"],
+            "id": db_id
+        }
+
+        put_response = self.tester.put(self.url + str(srv_grp) + '/' +
+                                       str(server_id) + '/' + str(db_id),
+                                       data=json.dumps(data),
+                                       follow_redirects=True)
+        self.assertEquals(put_response.status_code, 200)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
+
diff --git a/web/pgadmin/browser/server_groups/servers/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/tests/__init__.py
index 28cdb94..55a3a17 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class ServerGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        print ("In ServerGenerateTestCase...")
+        return
\ No newline at end of file
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 0af13d3..3592cf2 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
@@ -9,45 +9,47 @@
 
 import json
 
-from pgadmin.browser.tests.test_login import LoginTestCase
-from regression.config import config_data
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 
 
-class ServersAddTestCase(LoginTestCase):
-    """
-    This class will add the servers under default server group and verify with
-    server's name.
-    """
-
-    priority = 4
+class ServersAddTestCase(BaseTestGenerator):
+    """ This class will add the servers under default server group. """
 
     scenarios = [
         # Fetch the default url for server object
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def runTest(self):
+    def setUp(self):
         """
-        This function will add the server under default server group.
-        Verify the added server with response code as well as server name.
+        This function login the test account before running the logout
+        test case
         """
 
-        srv_grp = config_data['test_server_group']
-
-        for srv in config_data['test_server_credentials']:
-            data = {"name": srv['test_name'],
-                    "comment": "",
-                    "host": srv['test_host'],
-                    "port": srv['test_db_port'],
-                    "db": srv['test_maintenance_db'],
-                    "username": srv['test_db_username'],
-                    "role": "",
-                    "sslmode": srv['test_sslmode']}
+        utils.login_tester_account(self.tester)
 
-            url = self.url + str(srv_grp) + "/"
+    def runTest(self):
+        """ This function will add the server under default server group."""
 
-            response = self.tester.post(url, data=json.dumps(data),
+        server_group, config_data, pickle_id_dict = utils.get_config_data()
+        for server_data in config_data:
+            url = "{0}{1}/".format(self.url, server_group)
+            response = self.tester.post(url, data=json.dumps(server_data),
                                         content_type='html/json')
+
             self.assertTrue(response.status_code, 200)
-            respdata = json.loads(response.data)
-            self.assertTrue(respdata['node']['label'], srv['test_name'])
+
+            response_data = json.loads(response.data.decode())
+            utils.write_parent_id(response_data, pickle_id_dict)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
index 329d74f..1e9a686 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
@@ -9,49 +9,56 @@
 
 import json
 
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 from regression.config import config_data
 
 
-class ServersDeleteTestCase(LoginTestCase):
-    """
-    This class will check server node present on the object browser's tree node
-    by response code.
-    """
-    priority = 7
+class ServerDeleteTestCase(BaseTestGenerator):
+    """ This class will delete the last server present under tree node."""
 
     scenarios = [
         # Fetching the default url for server node
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def runTest(self):
+    def setUp(self):
         """
-        This function will get all available servers under object browser
-        and delete the servers using server id.
+        This function perform the two tasks
+         1. Login to test client
+         2. Add the test server
+
+        :return: None
         """
 
-        srv_grp = config_data['test_server_group']
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
 
-        for srv in config_data['test_server_credentials']:
+    def runTest(self):
+        """ This function will get all available servers under object browser
+        and delete the last server using server id."""
 
-            data = {"name": srv['test_name'],
-                    "host": srv['test_host'],
-                    "port": srv['test_db_port'],
-                    "db": srv['test_maintenance_db'],
-                    "username": srv['test_db_username'],
-                    "role": "",
-                    "sslmode": srv['test_sslmode']}
+        srv_grp = config_data['test_server_group']
+        url = self.url + str(srv_grp) + "/"
+        response = self.tester.get(url)
+        response_data = json.loads(response.data.decode())
+        if len(response_data) == 0:
+            raise Exception("No server(s) to delete!!!")
 
-            url = self.url + str(srv_grp) + "/"
+        # Delete last server
+        server = response_data[-1]
+        response = self.tester.delete(url + str(server['id']))
+        self.assertTrue(response.status_code, 200)
+        response_data = json.loads(response.data.decode())
+        self.assertTrue(response_data['success'], 1)
 
-            response = self.tester.get(url, data=json.dumps(data),
-                                       content_type='html/json')
-            self.assertTrue(response.status_code, 200)
-            respdata = json.loads(response.data)
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
 
-            for server in respdata:
-                response = self.tester.delete(url + json.dumps(server['id']))
-                self.assertTrue(response.status_code, 200)
-                respdata = json.loads(response.data)
-                self.assertTrue(respdata['success'], 1)
+        :return: None
+        """
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
index 050843e..abf49a3 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
@@ -7,43 +7,53 @@
 #
 # ##########################################################################
 
-import json
-
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 from regression.config import config_data
+from regression.test_utils import get_ids
 
 
-class ServersGetTestCase(LoginTestCase):
+class ServersGetTestCase(BaseTestGenerator):
     """
-    This class will check server node present on the object browser's tree node
+    This class will fetch added servers under default server group
     by response code.
     """
 
-    priority = 5
-
     scenarios = [
         # Fetch the default url for server node
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def runTest(self):
+    def setUp(self):
         """
-        This function will get all available servers present under
-        object browser.
+        This function perform the two tasks
+         1. Login to test client
+         2. Add the test server
+
+        :return: None
         """
 
+        utils.login_tester_account(self.tester)
+        utils.add_server(self.tester)
+
+    def runTest(self):
+        """ This function will fetch the added servers to object browser. """
+
+        all_id = get_ids()
+        server_ids = all_id["sid"]
         srv_grp = config_data['test_server_group']
 
-        for srv in config_data['test_server_credentials']:
-            data = {"name": srv['test_name'],
-                    "host": srv['test_host'],
-                    "port": srv['test_db_port'],
-                    "db": srv['test_maintenance_db'],
-                    "username": srv['test_db_username'],
-                    "role": "",
-                    "sslmode": srv['test_sslmode']}
-
-            url = self.url + str(srv_grp) + "/"
-            response = self.tester.get(url, data=json.dumps(data),
-                                       content_type='html/json')
-            self.assertTrue(response.status_code, 200)
+        for server_id in server_ids:
+            url = "{0}{1}/{2}".format(self.url, srv_grp, server_id)
+            response = self.tester.get(url, content_type='html/json')
+            self.assertEquals(response.status_code, 200)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
index 306bb03..e2cd329 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
@@ -9,57 +9,66 @@
 
 import json
 
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 from regression.config import config_data
 
 
-class ServersUpdateTestCase(LoginTestCase):
-    """
-    This class will check server node present on the object browser's tree node
-    by response code.
-    """
-
-    priority = 6
+class ServerUpdateTestCase(BaseTestGenerator):
+    """ This class will update server's comment field. """
 
     scenarios = [
         # Fetching the default url for server node
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def runTest(self):
-        """
-        This function will edit and update the server's comment field
-        by the server id.
+    def setUp(self):
         """
+        This function perform the four tasks
+         1. Login to test client
+         2. Add the test server
+         3. Get the server
+         4. Connect to server
 
-        srv_grp = config_data['test_server_group']
+        :return: None
+        """
 
-        for srv in config_data['test_server_credentials']:
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
+        # Get the server
+        utils.get_server(self.tester)
+        # Connect to server
+        self.server_connect, self.server_group, self.server_id = \
+            utils.connect_server(self.tester)
+        if len(self.server_connect) == 0:
+            raise Exception("No Server(s) connected to update!!!")
 
-            data = {"name": srv['test_name'],
-                    "host": srv['test_host'],
-                    "port": srv['test_db_port'],
-                    "db": srv['test_maintenance_db'],
-                    "username": srv['test_db_username'],
-                    "role": "",
-                    "sslmode": srv['test_sslmode']}
+    def runTest(self):
+        """ This function will update the server's comment field. """
 
-            url = self.url + str(srv_grp) + "/"
+        data = {
+            "comment":
+                config_data['test_server_update_data']['test_comment'],
+            "id": self.server_id
+        }
 
-            response = self.tester.get(url, data=json.dumps(data),
-                                       content_type='html/json')
+        put_response = self.tester.put(
+            self.url + str(self.server_group) + '/' +
+            str(self.server_id), data=json.dumps(data),
+            content_type='html/json')
+        self.assertEquals(put_response.status_code, 200)
 
-            self.assertTrue(response.status_code, 200)
-            respdata = json.loads(response.data)
+        response_data = json.loads(put_response.data.decode())
+        self.assertTrue(response_data['success'], 1)
 
-            for server in respdata:
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
 
-                url = self.url + str(srv_grp) + "/" + json.dumps(server['id'])
+        :return: None
+        """
 
-                for server in config_data['test_server_update_data']:
-                    data = {"comment": server['test_comment']}
-                    response = self.tester.put(url, data=json.dumps(data),
-                                               content_type='html/json')
-                    self.assertTrue(response.status_code, 200)
-                    respdata = json.loads(response.data)
-                    self.assertTrue(respdata['success'], 1)
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/tests/__init__.py b/web/pgadmin/browser/server_groups/tests/__init__.py
index 9fabed9..7fdd5c7 100644
--- a/web/pgadmin/browser/server_groups/tests/__init__.py
+++ b/web/pgadmin/browser/server_groups/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class SGGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        print ("In SGGenerateTestCase...")
+        return
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/tests/test_sg_add.py b/web/pgadmin/browser/server_groups/tests/test_sg_add.py
index e70bb65..07bbe96 100644
--- a/web/pgadmin/browser/server_groups/tests/test_sg_add.py
+++ b/web/pgadmin/browser/server_groups/tests/test_sg_add.py
@@ -9,28 +9,40 @@
 
 import json
 
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 from regression.config import config_data
 
 
-class SgNodeTestCase(LoginTestCase):
+class SgNodeTestCase(BaseTestGenerator):
     """
      This class will check available server groups in pgAdmin.
     """
 
-    priority = 1
-
     scenarios = [
         # Fetching the default url for server group node
         ('Check Server Group Node', dict(url='/browser/server-group/obj/'))
     ]
 
+    def setUp(self):
+        """
+        This function login the test account before running the logout
+        test case
+        """
+
+        utils.login_tester_account(self.tester)
+
     def runTest(self):
         """This function will check available server groups."""
 
-        i = config_data['test_server_group']
-
-        response = self.tester.get(self.url + str(i), content_type='html/json')
+        server_group_id = config_data['test_server_group']
+        response = self.tester.get(self.url + str(server_group_id),
+                                   content_type='html/json')
         self.assertTrue(response.status_code, 200)
-        respdata = json.loads(response.data)
-        self.assertTrue(respdata['id'], i)
+        response_data = json.loads(response.data.decode('utf8'))
+        self.assertTrue(response_data['id'], server_group_id)
+
+    def tearDown(self):
+        """This function logout the test account """
+
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/__init__.py b/web/pgadmin/browser/tests/__init__.py
index 2381efd..3fab6fe 100644
--- a/web/pgadmin/browser/tests/__init__.py
+++ b/web/pgadmin/browser/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class BrowserGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        print ("In BrowserGenerateTestCase...")
+        return
\ No newline at end of file
diff --git a/web/pgadmin/browser/tests/test_change_password.py b/web/pgadmin/browser/tests/test_change_password.py
index dedb7d9..8b47e25 100644
--- a/web/pgadmin/browser/tests/test_change_password.py
+++ b/web/pgadmin/browser/tests/test_change_password.py
@@ -9,19 +9,18 @@
 
 import uuid
 
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
 from regression.config import config_data
+from regression import test_utils as utils
 
 
-class ChangePasswordTestCase(LoginTestCase):
+class ChangePasswordTestCase(BaseTestGenerator):
     """
     This class validates the change password functionality
     by defining change password scenarios; where dict of
     parameters describes the scenario appended by test name.
     """
 
-    priority = 2
-
     scenarios = [
         # This testcase validates invalid confirmation password
         ('TestCase for Validating Incorrect_New_Password', dict(
@@ -48,8 +47,7 @@ class ChangePasswordTestCase(LoginTestCase):
             new_password='', new_password_confirm='',
             respdata='Password not provided')),
 
-        # This testcase validates if current entered password
-        # is incorrect
+        # This testcase validates if current entered password is incorrect
         ('TestCase for Validating Incorrect_Current_Password', dict(
             password=str(uuid.uuid4())[4:8],
             new_password=(config_data['pgAdmin4_login_credentials']
@@ -70,6 +68,7 @@ class ChangePasswordTestCase(LoginTestCase):
                 ['test_new_password']),
             respdata='You successfully changed your password.')),
         ('Reassigning_Password', dict(
+            test_case='reassigning_password',
             password=(config_data['pgAdmin4_login_credentials']
                       ['test_new_password']),
             new_password=(config_data['pgAdmin4_login_credentials']
@@ -81,14 +80,44 @@ class ChangePasswordTestCase(LoginTestCase):
 
     ]
 
+    def setUp(self):
+        """
+        This function login the test account before running the logout
+        test case
+        """
+
+        utils.login_tester_account(self.tester)
+
     def runTest(self):
         """This function will check change password functionality."""
 
+        # Check for 'test_case' exists in self For reassigning the password.
+        # Password gets change in change password test case.
+        if 'test_case' in dir(self):
+            email = \
+                config_data['pgAdmin4_login_credentials'][
+                    'test_login_username']
+            password = \
+                config_data['pgAdmin4_login_credentials'][
+                    'test_new_password']
+            response = self.tester.post('/login', data=dict(
+                email=email, password=password), follow_redirects=True)
+
         response = self.tester.get('/change', follow_redirects=True)
-        self.assertIn('pgAdmin 4 Password Change', response.data)
+        self.assertIn('pgAdmin 4 Password Change', response.data.decode())
+
         response = self.tester.post('/change', data=dict(
             password=self.password,
             new_password=self.new_password,
             new_password_confirm=self.new_password_confirm),
                                     follow_redirects=True)
-        self.assertIn(self.respdata, response.data)
+        self.assertIn(self.respdata, response.data.decode())
+
+    def tearDown(self):
+        """
+        This function logout the test client
+
+        :return: None
+        """
+
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/test_login.py b/web/pgadmin/browser/tests/test_login.py
index 7c2b796..8856700 100644
--- a/web/pgadmin/browser/tests/test_login.py
+++ b/web/pgadmin/browser/tests/test_login.py
@@ -8,9 +8,9 @@
 ##########################################################################
 
 import uuid
-
 from pgadmin.utils.route import BaseTestGenerator
 from regression.config import config_data
+from regression import test_utils as utils
 
 
 class LoginTestCase(BaseTestGenerator):
@@ -20,8 +20,6 @@ class LoginTestCase(BaseTestGenerator):
     describe the scenario appended by test name.
     """
 
-    priority = 0
-
     scenarios = [
         # This test case validates the invalid/incorrect password
         ('TestCase for Checking Invalid_Password', dict(
@@ -67,13 +65,28 @@ class LoginTestCase(BaseTestGenerator):
                    ['test_login_username']),
             password=(config_data['pgAdmin4_login_credentials']
                       ['test_login_password']),
-            respdata='You are currently running version'))
+            respdata='Gravatar image for %s' %
+                     config_data['pgAdmin4_login_credentials']
+                     ['test_login_username']))
     ]
 
+    def setUp(self):
+        pass
+
     def runTest(self):
         """This function checks login functionality."""
 
         response = self.tester.post('/login', data=dict(
             email=self.email, password=self.password),
                                     follow_redirects=True)
-        self.assertIn(self.respdata, response.data)
+        self.assertIn(self.respdata, response.data.decode('utf8'))
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/test_logout.py b/web/pgadmin/browser/tests/test_logout.py
index 8971e72..c2ccf94 100644
--- a/web/pgadmin/browser/tests/test_logout.py
+++ b/web/pgadmin/browser/tests/test_logout.py
@@ -7,38 +7,33 @@
 #
 # ##########################################################################
 
-from pgadmin.browser.tests.test_login import LoginTestCase
-from regression.config import config_data
 
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 
-class LogoutTest(LoginTestCase):
+
+class LogoutTest(BaseTestGenerator):
     """
     This class verifies the logout functionality; provided the user is already
     logged-in. Dictionary parameters define the scenario appended by test
     name.
     """
 
-    priority = 3
-
     scenarios = [
         # This test case validate the logout page
         ('Logging Out', dict(respdata='Redirecting...'))
     ]
 
+    def setUp(self):
+        """
+        This function login the test account before running the logout
+        test case
+        """
+
+        utils.login_tester_account(self.tester)
+
     def runTest(self):
         """This function checks the logout functionality."""
 
         response = self.tester.get('/logout')
-        self.assertIn(self.respdata, response.data)
-
-    def tearDown(self):
-        """
-        Defining tear down class, which will run after each test method execute.
-        Re-logging in as further modules require login.
-        """
-
-        self.tester.post('/login', data=dict(
-            email=(config_data['pgAdmin4_login_credentials']
-                   ['test_login_username']),
-            password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password'])), follow_redirects=True)
+        self.assertIn(self.respdata, response.data.decode('utf8'))
diff --git a/web/pgadmin/browser/tests/test_reset_password.py b/web/pgadmin/browser/tests/test_reset_password.py
index 030b182..26dd80c 100644
--- a/web/pgadmin/browser/tests/test_reset_password.py
+++ b/web/pgadmin/browser/tests/test_reset_password.py
@@ -11,6 +11,7 @@ import uuid
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression.config import config_data
+from regression import test_utils as utils
 
 
 class ResetPasswordTestCase(BaseTestGenerator):
@@ -19,7 +20,6 @@ class ResetPasswordTestCase(BaseTestGenerator):
     scenarios; Each dict parameter describe a scenario appended by
     test name.
     """
-    priority = 1
 
     scenarios = [
         # This test case validates the empty email field
@@ -37,12 +37,29 @@ class ResetPasswordTestCase(BaseTestGenerator):
             ['test_login_username'], respdata='pgAdmin 4'))
     ]
 
+    def setUp(self):
+        """
+        This function login the test account before running the logout
+        test case
+        """
+
+        utils.login_tester_account(self.tester)
+
     def runTest(self):
         """This function checks reset password functionality."""
 
         response = self.tester.get('/reset')
-        self.assertIn('Recover pgAdmin 4 Password', response.data)
+        self.assertIn('Recover pgAdmin 4 Password', response.data.decode())
         response = self.tester.post(
             '/reset', data=dict(email=self.email),
             follow_redirects=True)
-        self.assertIn(self.respdata, response.data)
+        self.assertIn(self.respdata, response.data.decode())
+
+    def tearDown(self):
+        """
+        This function logout the test client
+
+        :return: None
+        """
+
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/utils/route.py b/web/pgadmin/utils/route.py
index fb9de69..a2cd1eb 100644
--- a/web/pgadmin/utils/route.py
+++ b/web/pgadmin/utils/route.py
@@ -52,8 +52,10 @@ class TestsGeneratorRegistry(ABCMeta):
         from werkzeug.utils import find_modules
 
         for module_name in find_modules(pkg, False, True):
-            module = import_module(module_name)
-
+            try:
+                module = import_module(module_name)
+            except ImportError:
+                pass
 
 import six
 
diff --git a/web/regression/README b/web/regression/README
index e0003e4..ef9fd29 100644
--- a/web/regression/README
+++ b/web/regression/README
@@ -40,29 +40,40 @@ General Information
     3. test_server_get.py
     4. test_server_update.py
 
-2) The pgAdmin4 source tree includes a file template for the server configuration
-   named ‘test_config.json.in' in the ‘pgAdmin4/web/regression’ directory. After
-   completing the pgAdmin4 configuration, you must make a working copy of the
-   template called test_config.json before modifying the file contents.
+2) The pgAdmin4 source tree includes 2 different configuration file templates.
+   One file template for the server configuration
+   named ‘test_config.json.in' and another for test configuration named
+   'test_advance_config.json.in' in the ‘pgAdmin4/web/regression’ directory.
+   After completing the pgAdmin4 configuration, you must make a working copy of
+   the templates called test_config.json and test_advance_config.json
+   before modifying the file contents.
 
-	2a) The following command copies the test_config.json.in file, creating a
-	    configuration file named test_config.json
+    2a) The following command copies the test_config.json.in file, creating a
+        configuration file named test_config.json (same way user can copy
+        test_advance_config.json.in file into test_advance_config.json)
 
-            # cp pgadmin4/web/regression/test_config.json.in \
-              pgadmin4/web/regression/test_config.json
+             # cp pgadmin4/web/regression/test_config.json.in \
+               pgadmin4/web/regression/test_config.json
 
-	2b) After creating the server configuration file, add (or modify)
-	    parameter values as per requirements. The configuration
-	    files are owned by root/user. The pgAdmin4 regression framework expects
-	    to find the files in the  directory '/<installation dir>/web/regression/'.
-	    If you move the file to another location, you must create a symbolic link
-	    that specifies the new location.
+    2b) After creating the server and test configuration file, add (or modify)
+        parameter values as per requirements. The configuration
+        files are owned by root/user. The pgAdmin4 regression framework expects
+        to find the files in the  directory '/<installation dir>/web/regression/'.
+        If you move the file to another location, you must create a symbolic
+        link that specifies the new location.
 
-	2c) Specifying Server Configuration file:
+    2c) Specifying Server Configuration file:
+
+        server details and connection properties as per their local setup. The
+        test_config file is in json format and property values are
+        case-sensitive.
+
+    2d) Specifying the Test Configuration file:
+
+        The user can add/change test data as per their need. The
+        test_advance_config file is in json format and property values are
+        case-sensitive.
 
-	    The user can use the parameters in the configuration file to specify the
-	    server details and connection properties as per their local setup. The
-	    test_config file is in json format and property values are case-sensitive.
 
 Test Data Details
 -----------------
@@ -92,5 +103,18 @@ Execution:
   and registered automatically by its module name in
   'pgadmin4/web/pgadmin/utils/test.py' file.
 
-- Execute test framework run 'regression/testsuite.py' file.
+- As the test framework is modular and dynamically locates the tests
+  package, We can now executes test framework node wise
+
+- Execute test framework for all nodes
+     run 'regression/testsuite.py --pkg all'
+
+- Execute test framework for single node at a time
+
+     Example 1) Run test framework for 'browser' node
+     run 'regression/testsuite.py --pkg browser'
+
+     Example 2) Run test framework for 'database' node
+     run 'regression/testsuite.py --pkg browser.server_groups.servers.databases'
+
 
diff --git a/web/regression/config.py b/web/regression/config.py
index bef65fb..f48eade 100644
--- a/web/regression/config.py
+++ b/web/regression/config.py
@@ -14,3 +14,8 @@ root = os.path.dirname(os.path.realpath(__file__))
 
 with open(root + '/test_config.json') as data_file:
     config_data = json.load(data_file)
+
+with open(root + '/test_advance_config.json') as data_file:
+    advance_config_data = json.load(data_file)
+
+pickle_path = os.path.join(root, 'parent_id.pkl')
diff --git a/web/regression/test_advance_config.json.in b/web/regression/test_advance_config.json.in
new file mode 100644
index 0000000..bcb867c
--- /dev/null
+++ b/web/regression/test_advance_config.json.in
@@ -0,0 +1,105 @@
+{
+  "test_add_database_data": [
+   {
+    "test_privileges_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "C",
+            "privilege": true,
+            "with_grant": true
+          },
+          {
+            "privilege_type": "T",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_conn_limit": -1,
+    "test_owner": "postgres",
+    "test_fun_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "X",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_seq_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "r",
+            "privilege": true,
+            "with_grant": false
+          },
+          {
+            "privilege_type": "w",
+            "privilege": true,
+            "with_grant": false
+          },
+          {
+            "privilege_type": "U",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_tbl_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "a",
+            "privilege": true,
+            "with_grant": true
+          },
+          {
+            "privilege_type": "r",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_type_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "U",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_encoding": "UTF8",
+    "test_name": "test_db_automation",
+    "test_privileges": [],
+    "test_securities": [],
+    "test_variables": []
+  }
+ ],
+
+  "test_db_update_data": [
+  {
+      "test_comment": "This is db update comment"
+  }
+ ]
+
+}
\ No newline at end of file
diff --git a/web/regression/test_nodes.py b/web/regression/test_nodes.py
new file mode 100644
index 0000000..0fa4695
--- /dev/null
+++ b/web/regression/test_nodes.py
@@ -0,0 +1,40 @@
+# ##################################################################
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from regression.config import config_data
+from regression.test_utils import get_ids
+
+
+def test_getnodes(node=None):
+    # Connect to server and database.
+
+    if not node:
+        return None
+
+    all_id = get_ids()
+
+    server_id = all_id["sid"][0]
+    db_id = all_id["did"][0]
+    srv_grp = config_data['test_server_group']
+
+    # Connect to server
+    response = node.tester.post('browser/server/connect/{0}/{1}'.format(
+        srv_grp, server_id), data = dict(
+        password=config_data['test_server_credentials'][0]['test_db_password']),
+        follow_redirects = True)
+
+    # Connect to database
+    con_response = node.tester.post(
+        'browser/database/connect/{0}/{1}/{2}'.format(
+            srv_grp, server_id, db_id), follow_redirects = True)
+
+    db_con = json.loads(con_response.data.decode())
+
+    return db_con
\ No newline at end of file
diff --git a/web/regression/test_utils.py b/web/regression/test_utils.py
new file mode 100644
index 0000000..f21de54
--- /dev/null
+++ b/web/regression/test_utils.py
@@ -0,0 +1,289 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import os
+import pickle
+import json
+import uuid
+
+import config
+from regression.config import config_data
+
+SERVER_URL = '/browser/server/obj/'
+SERVER_CONNECT_URL = 'browser/server/connect/'
+DATABASE_CONNECT_URL = '/browser/database/obj/'
+
+
+def get_ids(url=config.APP_ROOT + '/regression/parent_id.pkl'):
+    """
+    This function read the parent node's id and return it
+
+    :param url: file path from which it will red the ids
+    :type url: str
+    :return: node ids
+    :rtype: dict
+    """
+
+    output = open(url, 'rb')
+    ids = pickle.load(output)
+    output.close()
+
+    return ids
+
+
+def login_tester_account(tester):
+    """
+    This function login the test account using credentials mentioned in
+    config file
+
+    :param tester: test client
+    :type tester: flask test client object
+    :return: None
+    """
+
+    email = \
+        config_data['pgAdmin4_login_credentials']['test_login_username']
+    password = \
+        config_data['pgAdmin4_login_credentials']['test_login_password']
+    response = tester.post('/login', data=dict(
+        email=email, password=password), follow_redirects=True)
+
+
+def logout_tester_account(tester):
+    """
+    This function logout the test account
+
+    :param tester: test client
+    :type tester: flask test client object
+    :return: None
+    """
+
+    response = tester.get('/logout')
+
+
+def get_config_data():
+    """
+    This function get the data related to server group and database
+    like db name, host, port and username etc.
+
+    :return: server_group, db_data, pickle_id_dict
+    :rtype: server_group:dict, db_data:list, pickle_id_dict:dict
+    """
+
+    db_data = []
+
+    pickle_id_dict = {
+        "sid": [],  # server
+        "did": [],  # database
+        "lrid": [],  # login role
+        "tsid": [],  # tablspace
+        "cid": [],  # cast
+        "eid": [],  # extention
+        "lid": [12397],  # language
+        "scid": [],  # schema
+        "tfnid": [],  # trigger function
+        "etid": [],  # event trigger
+        "coid": [],  # collation
+        "fid": [],  # FDW
+        "doid": [],  # Domain
+        "seid": [],  # Sequence
+        "tid": [],  # table
+        "vid": [],  # view
+        "mvid": [],  # mview
+        "fsid": [],  # foreign server
+        "umid": [],  # User mapping
+        "foid": []  # foreign table
+    }
+
+    server_group = config_data['test_server_group']
+
+    for srv in config_data['test_server_credentials']:
+        data = {"name": srv['test_name'],
+                "comment": "",
+                "host": srv['test_host'],
+                "port": srv['test_db_port'],
+                "db": srv['test_maintenance_db'],
+                "username": srv['test_db_username'],
+                "role": "",
+                "sslmode": srv['test_sslmode']}
+        db_data.append(data)
+    return server_group, db_data, pickle_id_dict
+
+
+def write_parent_id(response_data, pickle_id_dict):
+    """
+    This function writes the server's details to file parent_id.pkl
+
+    :param response_data: server's data
+    :type response_data: list of dictionary
+    :param pickle_id_dict: contains ids of server,database,tables etc.
+    :type pickle_id_dict: dict
+    :return: None
+    """
+
+    server_id = response_data['node']['_id']
+    if os.path.isfile(config.APP_ROOT + '/regression/parent_id.pkl'):
+        existed_server_id = open(
+            config.APP_ROOT + '/regression/parent_id.pkl', 'rb')
+        pickle_id_dict = pickle.load(existed_server_id)
+
+    pickle_id_dict["sid"].append(server_id)
+    output = open(config.APP_ROOT + '/regression/parent_id.pkl', 'wb')
+    pickle.dump(pickle_id_dict, output)
+    output.close()
+
+
+def write_db_parent_id(response_data):
+    """
+    This function writes the server and database related data like server
+    name, server id , database name, database id etc.
+
+    :param response_data: server and databases details
+    :type response_data: dict
+    :return: None
+    """
+
+    db_id = response_data['node']['_id']
+    if os.path.isfile(config.APP_ROOT + '/regression/parent_id.pkl'):
+        existing_server_id = open(
+            config.APP_ROOT + '/regression/parent_id.pkl', 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+
+        pickle_id_dict["did"].append(db_id)
+
+        db_output = open(
+            config.APP_ROOT + '/regression/parent_id.pkl', 'wb')
+        pickle.dump(pickle_id_dict, db_output)
+        db_output.close()
+
+
+def delete_parent_id_file():
+    """
+    This function deletes the file parent_id.pkl which contains server and
+    database details
+
+    :return: None
+    """
+
+    if os.path.isfile(config.APP_ROOT + '/regression/parent_id.pkl'):
+        os.remove(config.APP_ROOT + '/regression/parent_id.pkl')
+
+
+def add_server(tester):
+    """
+    This function add the server in the existing server group
+
+    :param tester: test object
+    :type tester: flask test object
+    :return:None
+    """
+
+    server_group, db_data, pickle_id_dict = get_config_data()
+    url = "{0}{1}/".format(SERVER_URL, server_group)
+    response = tester.post(url, data=json.dumps(db_data[0]),
+                           content_type='html/json')
+    response_data = json.loads(response.data.decode())
+    write_parent_id(response_data, pickle_id_dict)
+
+
+def get_server(tester):
+    """
+    This function gets the added serer details
+
+    :param tester: test client object
+    :type tester: flask test object
+    :return: response_data
+    :rtype: list
+    """
+
+    all_id = get_ids()
+    server_id = all_id["sid"][0]
+    server_group = config_data['test_server_group']
+
+    response = tester.get(SERVER_URL + str(server_group) + '/' +
+                          str(server_id),
+                          follow_redirects=True)
+    response_data = json.loads(response.data.decode())
+    return response_data
+
+
+def connect_server(tester):
+    """
+    This function used to connect added server
+
+    :param tester:test client object
+    :type tester: flask test object
+    :return: server_connect, server_group, server_id
+    :rtype: server_connect:dict, server_group:dict, server_id:str
+    """
+
+    srv_id = get_ids()
+    server_id = srv_id["sid"][0]
+    server_group = config_data['test_server_group']
+    response = tester.post(SERVER_CONNECT_URL + str(server_group) +
+                           '/' + server_id,
+                           data=dict(
+                               password=config_data
+                               ['test_server_credentials'][0]
+                               ['test_db_password']),
+                           follow_redirects=True)
+    server_connect = json.loads(response.data.decode())
+    connect_database(tester, server_connect, server_id, server_group)
+    return server_connect, server_group, server_id
+
+
+def connect_database(tester, server_connect, server_id, server_group):
+    """
+    This function is used to connect database and writes it's details to
+    file 'parent_id.pkl'
+
+    :param tester: test client object
+    :type tester: flask test client object
+    :param server_connect: server's data
+    :type server_connect: dict
+    :param server_id: server id
+    :type server_id: str
+    :param server_group: server group name
+    :type server_group: str
+    :return: None
+    """
+
+    if server_connect['data']['connected']:
+        data = {
+            "datacl": config_data['test_add_database_data']
+            ['test_privileges_acl'],
+            "datconnlimit": config_data['test_add_database_data']
+            ['test_conn_limit'],
+            "datowner": config_data['test_add_database_data']
+            ['test_owner'],
+            "deffuncacl": config_data['test_add_database_data']
+            ['test_fun_acl'],
+            "defseqacl": config_data['test_add_database_data']
+            ['test_seq_acl'],
+            "deftblacl": config_data['test_add_database_data']
+            ['test_tbl_acl'],
+            "deftypeacl": config_data['test_add_database_data']
+            ['test_type_acl'],
+            "encoding": config_data['test_add_database_data']
+            ['test_encoding'],
+            "name": str(uuid.uuid4())[1:8],
+            "privileges": config_data['test_add_database_data']
+            ['test_privileges'],
+            "securities": config_data['test_add_database_data']
+            ['test_securities'],
+            "variables": config_data['test_add_database_data']
+            ['test_variables']
+        }
+        db_response = tester.post(
+            DATABASE_CONNECT_URL + str(server_group) + "/" + server_id + "/",
+            data=json.dumps(data),
+            content_type='html/json')
+        response_data = json.loads(db_response.data.decode())
+        write_db_parent_id(response_data)
diff --git a/web/regression/testsuite.py b/web/regression/testsuite.py
index 75d437b..c342805 100644
--- a/web/regression/testsuite.py
+++ b/web/regression/testsuite.py
@@ -10,70 +10,140 @@
 """ This file collect all modules/files present in tests directory and add
 them to TestSuite. """
 
+import argparse
 import os
 import sys
 import unittest
+import logging
 
 from testscenarios.scenarios import generate_scenarios
 
-# We need to include the root directory in sys.path to ensure that we can
-# find everything we need when running in the standalone runtime.
-current_path = os.path.dirname(os.path.realpath(__file__))
-root = os.path.dirname(current_path)
+CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
 
-if sys.path[0] != root:
-    sys.path.insert(0, root)
 
-from pgadmin import create_app
-import config
+def create_pgadmin_app():
+    """
+    This function creates the pgadmin app for testing
 
-# Get the config database schema version. We store this in pgadmin.model
-# as it turns out that putting it in the config files isn't a great idea
-from pgadmin.model import SCHEMA_VERSION
-config.SETTINGS_SCHEMA_VERSION = SCHEMA_VERSION
+    :return: test client
+    :rtype: test app object
+    """
 
-# Create the app!
-app = create_app()
+    # Set sys path to current directory so that we can import pgadmin package
+    root = os.path.dirname(CURRENT_PATH)
+    if sys.path[0] != root:
+        sys.path.insert(0, root)
 
-# Disabling Cross-site request forgery(CSRF token) for testing purpose.
-# CSRF prevent session against malicious Web site, or end users who wants to
-# execute unwanted actions.
-app.config['WTF_CSRF_ENABLED'] = False
+    from pgadmin import create_app
 
-from pgadmin.utils.route import TestsGeneratorRegistry
+    # Create the app
+    app = create_app()
+    app.config['WTF_CSRF_ENABLED'] = False
+    test_app_client = app.test_client()
 
-# Registry will load all the testcases/modules from pgadmin path those are
-# register as BaseTestGenerator.
-TestsGeneratorRegistry.load_generators('pgadmin')
+    return test_app_client
 
-# Create test client
-# werkzeug provides a test client which gives a simple interface to the
-# application. We can trigger test request to the application.
-test_client = app.test_client()
 
+def get_suite(arguments, test_app_client):
+    """
+     This function loads the all modules in the tests directory into testing
+     environment.
 
-def suite():
-    """ Defining test suite which will execute all the testcases present in
-    tests directory according to set priority."""
+    :param arguments: this is command line arguments for module name to
+    which test suite will run
+    :type arguments: str
+    :param test_app_client: test client
+    :type test_app_client: pgadmin app object
+    :return pgadmin_suite: test suite with test cases
+    :rtype: TestSuite
+    """
 
-    pgadmin_suite = unittest.TestSuite()
+    from pgadmin.utils.route import TestsGeneratorRegistry
 
     modules = []
+    pgadmin_suite = unittest.TestSuite()
 
+    # Load the test modules which are in given package(i.e. arguments.pkg)
+    if arguments.pkg == "all":
+        TestsGeneratorRegistry.load_generators('pgadmin')
+    else:
+        TestsGeneratorRegistry.load_generators('pgadmin.{}.tests'.format(
+            arguments.pkg))
+
+    # Get the each test module and add into list
     for key, klass in TestsGeneratorRegistry.registry.items():
         gen = klass
+        modules.append(gen)
 
-        modules.insert(gen.priority, gen)
-
-    for m in modules:
-        obj = m()
-        obj.setTestClient(test_client)
+    # Set the test client to each module & generate the scenarios
+    for module in modules:
+        obj = module()
+        obj.setTestClient(test_app_client)
         scenario = generate_scenarios(obj)
         pgadmin_suite.addTests(scenario)
 
     return pgadmin_suite
 
 
+def add_arguments():
+    """
+    This function parse the command line arguments(project's package name
+    e.g. browser) & add into parser
+
+    :return args: command line argument for pgadmin's package name
+    :rtype: argparse namespace
+    """
+
+    parser = argparse.ArgumentParser(description='Test suite for pgAdmin4')
+    parser.add_argument('--pkg', help='Executes the test cases of particular'
+                                      ' package')
+    arg = parser.parse_args()
+
+    return arg
+
+
+class StreamToLogger(object):
+    def __init__(self, logger, log_level=logging.INFO):
+        self.terminal = sys.stderr
+        self.logger = logger
+        self.log_level = log_level
+        self.linebuf = ''
+
+    def write(self, buf):
+        """
+        This function writes the log in the logger file as well as on console
+
+        :param buf: log message
+        :type buf: str
+        :return: None
+        """
+
+        self.terminal.write(buf)
+        for line in buf.rstrip().splitlines():
+            self.logger.log(self.log_level, line.rstrip())
+
+    def flush(self):
+        pass
+
+
 if __name__ == '__main__':
-    suite = suite()
-    tests = unittest.TextTestRunner(descriptions=True, verbosity=2).run(suite)
+    # Set basic logging configuration for log file
+    logging.basicConfig(level=logging.DEBUG,
+                        format='%(asctime)s:%(levelname)s:%(name)s:%(message)s',
+                        filename="logger.log",
+                        filemode='w'
+                        )
+
+    # Create logger to write log in the logger file with on console
+    stderr_logger = logging.getLogger('STDERR')
+    sys.stderr = StreamToLogger(stderr_logger, logging.ERROR)
+
+    # Create the pgadmin app
+    test_client = create_pgadmin_app()
+    args = add_arguments()
+    suite = get_suite(args, test_client)
+    tests = unittest.TextTestRunner(stream=sys.stderr, descriptions=True,
+                                    verbosity=2).run(suite)
+
+    print("\n\n Please check output in file: logger.log placed at ",
+          CURRENT_PATH)


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-11 11:41  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Dave Page @ 2016-07-11 11:41 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

On Fri, Jul 8, 2016 at 2:30 PM, Navnath Gadakh <
[email protected]> wrote:

>
> Hi Dave,
>
> PFA patch for modular API test cases.
>
> Kindly, review the same and let me know for any modification.
>

Please re-create the patch so that it doesn't revert various changes made
to config.py etc. over the last couple of weeks.

What is the patch for? Is it fixing issues in Priyanka's last patch, or
something else?

-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-11 13:16  Navnath Gadakh <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-07-11 13:16 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,
PFA updated patch for modular API test cases.

On Mon, Jul 11, 2016 at 5:11 PM, Dave Page <[email protected]>
wrote:

>
>
> On Fri, Jul 8, 2016 at 2:30 PM, Navnath Gadakh <
> [email protected]> wrote:
>
>>
>> Hi Dave,
>>
>> PFA patch for modular API test cases.
>>
>> Kindly, review the same and let me know for any modification.
>>
>
> Please re-create the patch so that it doesn't revert various changes made
> to config.py etc. over the last couple of weeks.
>

  config.py file was not updated at my end, I have updated it in the
current patch.  I have also added code related to advance test data
configuration which was created by Priyanka (Seprated the test data
configuration files).


> What is the patch for? Is it fixing issues in Priyanka's last patch, or
> something else?
> This patch is for -
> 1. Now we can run testsuite node/module wise(like for browser only, for
> databases only)  OR for all nodes/modules
> 2. I have modified the existing functionality for testsuite and all test
> case classes (Made all test cases independently runnable, removed
> the priority logic).
>

    For more details please refer the file 'regression/README'.



> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>



-- 
*Thanks,*
*Navnath Gadakh*
*Software Engineer*
*Phone : + 91 9975389878*


*The Postgres Database Company*


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [text/x-patch] pgadmin_unittest_modular.patch (63.2K, 3-pgadmin_unittest_modular.patch)
  download | inline diff:
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/tests/__init__.py
new file mode 100644
index 0000000..aa01297
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/__init__.py
@@ -0,0 +1,15 @@
+# ##########################################################################
+#
+# #pgAdmin 4 - PostgreSQL Tools
+#
+# #Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# #This software is released under the PostgreSQL Licence
+#
+# ##########################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class DatabaseCreateTestCase(BaseTestGenerator):
+    def runTest(self):
+        return
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
new file mode 100644
index 0000000..4cb5092
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
@@ -0,0 +1,93 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+import uuid
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import advance_config_data
+
+
+class DatabaseAddTestCase(BaseTestGenerator):
+    """
+    This class will check server group node present on the object browser's
+    tree node by response code.
+    """
+
+    scenarios = [
+        # Fetching default URL for database node.
+        ('Check Databases Node URL', dict(url='/browser/database/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function perform the two tasks
+         1. Login to test client
+         2. Add the test server
+
+        :return: None
+        """
+
+        utils.login_tester_account(self.tester)
+        # Add the server
+        utils.add_server(self.tester)
+
+    def runTest(self):
+        """ This function will add database under 1st server of tree node. """
+
+        server_connect_response, server_group, server_id = \
+            utils.connect_server(self.tester)
+
+        if server_connect_response['data']['connected']:
+            data = {
+                "datacl": advance_config_data['test_add_database_data'][0]
+                ['test_privileges_acl'],
+                "datconnlimit": advance_config_data
+                ['test_add_database_data'][0]['test_conn_limit'],
+                "datowner": advance_config_data
+                ['test_add_database_data'][0]['test_owner'],
+                "deffuncacl": advance_config_data
+                ['test_add_database_data'][0]['test_fun_acl'],
+                "defseqacl": advance_config_data
+                ['test_add_database_data'][0]['test_seq_acl'],
+                "deftblacl": advance_config_data
+                ['test_add_database_data'][0]['test_tbl_acl'],
+                "deftypeacl": advance_config_data
+                ['test_add_database_data'][0]['test_type_acl'],
+                "encoding": advance_config_data
+                ['test_add_database_data'][0]['test_encoding'],
+                "name": str(uuid.uuid4())[1:8],
+                "privileges": advance_config_data
+                ['test_add_database_data'][0]['test_privileges'],
+                "securities": advance_config_data
+                ['test_add_database_data'][0]['test_securities'],
+                "variables": advance_config_data
+                ['test_add_database_data'][0]['test_variables']
+            }
+
+            db_response = self.tester.post(self.url + str(server_group) + "/"
+                                           + server_id + "/",
+                                           data=json.dumps(data),
+                                           content_type='html/json')
+            self.assertTrue(db_response.status_code, 200)
+            response_data = json.loads(db_response.data.decode())
+            utils.write_db_parent_id(response_data)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
+
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
new file mode 100644
index 0000000..f21905b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
@@ -0,0 +1,70 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import config_data
+from regression.test_nodes import test_getnodes
+from regression.test_utils import get_ids
+
+
+class DatabaseDeleteTestCase(BaseTestGenerator):
+    """ This class will delete the database under last added server. """
+
+    scenarios = [
+        # Fetching default URL for database node.
+        ('Check Databases Node URL', dict(url='/browser/database/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function perform the three tasks
+         1. Login to test client
+         2. Add the test server
+         3. Connect to server
+
+        :return: None
+        """
+
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
+        # Secondly, connect to server/database
+        utils.connect_server(self.tester)
+
+    def runTest(self):
+        """ This function will delete the database."""
+
+        all_id = get_ids()
+        server_id = all_id["sid"][0]
+        db_id = all_id["did"][0]
+        srv_grp = config_data['test_server_group']
+        db_con = test_getnodes(node=self)
+        if len(db_con) == 0:
+            raise Exception("No database(s) to delete!!!")
+        response = self.tester.delete(self.url + str(srv_grp) + '/' +
+                                      str(server_id) + '/' + str(db_id),
+                                      follow_redirects=True)
+
+        response_data = json.loads(response.data.decode())
+        self.assertTrue(response_data['success'], 1)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
+
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
new file mode 100644
index 0000000..e07fbba
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
@@ -0,0 +1,67 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import config_data
+from regression.test_nodes import test_getnodes
+from regression.test_utils import get_ids
+
+
+class DatabasesGetTestCase(BaseTestGenerator):
+    """
+    This class will fetch database added under last added server.
+    """
+
+    scenarios = [
+        # Fetching default URL for database node.
+        ('Check Databases Node URL', dict(url='/browser/database/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function perform the three tasks
+         1. Login to test client
+         2. Add the test server
+         3. Connect to server
+
+        :return: None
+        """
+
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
+        # Secondly, connect to server/database
+        utils.connect_server(self.tester)
+
+    def runTest(self):
+        """ This function will fetch added database. """
+
+        all_id = get_ids()
+        server_id = all_id["sid"][0]
+        db_id = all_id["did"][0]
+        srv_grp = config_data['test_server_group']
+
+        db_con = test_getnodes(node=self)
+        if db_con["info"] == "Database connected.":
+            response = self.tester.get(self.url + str(srv_grp) + '/' +
+                                       str(server_id) + '/' + str(db_id),
+                                       follow_redirects=True)
+            self.assertEquals(response.status_code, 200)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
new file mode 100644
index 0000000..5d36400
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
@@ -0,0 +1,76 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import config_data, advance_config_data
+from regression.test_nodes import test_getnodes
+from regression.test_utils import get_ids
+
+
+class DatabasesUpdateTestCase(BaseTestGenerator):
+    """
+    This class will update the database under last added server.
+    """
+
+    scenarios = [
+        # Fetching default URL for database node.
+        ('Check Databases Node', dict(url='/browser/database/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function perform the three tasks
+         1. Login to test client
+         2. Add the test server
+         3. Connect to server
+
+        :return: None
+        """
+
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
+        # Secondly, connect to server/database
+        utils.connect_server(self.tester)
+
+    def runTest(self):
+        """ This function will update the comments field of database."""
+
+        all_id = get_ids()
+        server_id = all_id["sid"][0]
+        db_id = all_id["did"][0]
+        test_getnodes(node=self)
+        srv_grp = config_data['test_server_group']
+
+        data = {
+            "comments": advance_config_data["test_db_update_data"][0]
+            ["test_comment"],
+            "id": db_id
+        }
+
+        put_response = self.tester.put(self.url + str(srv_grp) + '/' +
+                                       str(server_id) + '/' + str(db_id),
+                                       data=json.dumps(data),
+                                       follow_redirects=True)
+        self.assertEquals(put_response.status_code, 200)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
+
diff --git a/web/pgadmin/browser/server_groups/servers/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/tests/__init__.py
index 28cdb94..55a3a17 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class ServerGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        print ("In ServerGenerateTestCase...")
+        return
\ No newline at end of file
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 0af13d3..3592cf2 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
@@ -9,45 +9,47 @@
 
 import json
 
-from pgadmin.browser.tests.test_login import LoginTestCase
-from regression.config import config_data
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 
 
-class ServersAddTestCase(LoginTestCase):
-    """
-    This class will add the servers under default server group and verify with
-    server's name.
-    """
-
-    priority = 4
+class ServersAddTestCase(BaseTestGenerator):
+    """ This class will add the servers under default server group. """
 
     scenarios = [
         # Fetch the default url for server object
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def runTest(self):
+    def setUp(self):
         """
-        This function will add the server under default server group.
-        Verify the added server with response code as well as server name.
+        This function login the test account before running the logout
+        test case
         """
 
-        srv_grp = config_data['test_server_group']
-
-        for srv in config_data['test_server_credentials']:
-            data = {"name": srv['test_name'],
-                    "comment": "",
-                    "host": srv['test_host'],
-                    "port": srv['test_db_port'],
-                    "db": srv['test_maintenance_db'],
-                    "username": srv['test_db_username'],
-                    "role": "",
-                    "sslmode": srv['test_sslmode']}
+        utils.login_tester_account(self.tester)
 
-            url = self.url + str(srv_grp) + "/"
+    def runTest(self):
+        """ This function will add the server under default server group."""
 
-            response = self.tester.post(url, data=json.dumps(data),
+        server_group, config_data, pickle_id_dict = utils.get_config_data()
+        for server_data in config_data:
+            url = "{0}{1}/".format(self.url, server_group)
+            response = self.tester.post(url, data=json.dumps(server_data),
                                         content_type='html/json')
+
             self.assertTrue(response.status_code, 200)
-            respdata = json.loads(response.data)
-            self.assertTrue(respdata['node']['label'], srv['test_name'])
+
+            response_data = json.loads(response.data.decode())
+            utils.write_parent_id(response_data, pickle_id_dict)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
index 329d74f..1e9a686 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
@@ -9,49 +9,56 @@
 
 import json
 
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 from regression.config import config_data
 
 
-class ServersDeleteTestCase(LoginTestCase):
-    """
-    This class will check server node present on the object browser's tree node
-    by response code.
-    """
-    priority = 7
+class ServerDeleteTestCase(BaseTestGenerator):
+    """ This class will delete the last server present under tree node."""
 
     scenarios = [
         # Fetching the default url for server node
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def runTest(self):
+    def setUp(self):
         """
-        This function will get all available servers under object browser
-        and delete the servers using server id.
+        This function perform the two tasks
+         1. Login to test client
+         2. Add the test server
+
+        :return: None
         """
 
-        srv_grp = config_data['test_server_group']
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
 
-        for srv in config_data['test_server_credentials']:
+    def runTest(self):
+        """ This function will get all available servers under object browser
+        and delete the last server using server id."""
 
-            data = {"name": srv['test_name'],
-                    "host": srv['test_host'],
-                    "port": srv['test_db_port'],
-                    "db": srv['test_maintenance_db'],
-                    "username": srv['test_db_username'],
-                    "role": "",
-                    "sslmode": srv['test_sslmode']}
+        srv_grp = config_data['test_server_group']
+        url = self.url + str(srv_grp) + "/"
+        response = self.tester.get(url)
+        response_data = json.loads(response.data.decode())
+        if len(response_data) == 0:
+            raise Exception("No server(s) to delete!!!")
 
-            url = self.url + str(srv_grp) + "/"
+        # Delete last server
+        server = response_data[-1]
+        response = self.tester.delete(url + str(server['id']))
+        self.assertTrue(response.status_code, 200)
+        response_data = json.loads(response.data.decode())
+        self.assertTrue(response_data['success'], 1)
 
-            response = self.tester.get(url, data=json.dumps(data),
-                                       content_type='html/json')
-            self.assertTrue(response.status_code, 200)
-            respdata = json.loads(response.data)
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
 
-            for server in respdata:
-                response = self.tester.delete(url + json.dumps(server['id']))
-                self.assertTrue(response.status_code, 200)
-                respdata = json.loads(response.data)
-                self.assertTrue(respdata['success'], 1)
+        :return: None
+        """
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
index 050843e..abf49a3 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
@@ -7,43 +7,53 @@
 #
 # ##########################################################################
 
-import json
-
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 from regression.config import config_data
+from regression.test_utils import get_ids
 
 
-class ServersGetTestCase(LoginTestCase):
+class ServersGetTestCase(BaseTestGenerator):
     """
-    This class will check server node present on the object browser's tree node
+    This class will fetch added servers under default server group
     by response code.
     """
 
-    priority = 5
-
     scenarios = [
         # Fetch the default url for server node
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def runTest(self):
+    def setUp(self):
         """
-        This function will get all available servers present under
-        object browser.
+        This function perform the two tasks
+         1. Login to test client
+         2. Add the test server
+
+        :return: None
         """
 
+        utils.login_tester_account(self.tester)
+        utils.add_server(self.tester)
+
+    def runTest(self):
+        """ This function will fetch the added servers to object browser. """
+
+        all_id = get_ids()
+        server_ids = all_id["sid"]
         srv_grp = config_data['test_server_group']
 
-        for srv in config_data['test_server_credentials']:
-            data = {"name": srv['test_name'],
-                    "host": srv['test_host'],
-                    "port": srv['test_db_port'],
-                    "db": srv['test_maintenance_db'],
-                    "username": srv['test_db_username'],
-                    "role": "",
-                    "sslmode": srv['test_sslmode']}
-
-            url = self.url + str(srv_grp) + "/"
-            response = self.tester.get(url, data=json.dumps(data),
-                                       content_type='html/json')
-            self.assertTrue(response.status_code, 200)
+        for server_id in server_ids:
+            url = "{0}{1}/{2}".format(self.url, srv_grp, server_id)
+            response = self.tester.get(url, content_type='html/json')
+            self.assertEquals(response.status_code, 200)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
index 306bb03..e2cd329 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
@@ -9,57 +9,66 @@
 
 import json
 
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 from regression.config import config_data
 
 
-class ServersUpdateTestCase(LoginTestCase):
-    """
-    This class will check server node present on the object browser's tree node
-    by response code.
-    """
-
-    priority = 6
+class ServerUpdateTestCase(BaseTestGenerator):
+    """ This class will update server's comment field. """
 
     scenarios = [
         # Fetching the default url for server node
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def runTest(self):
-        """
-        This function will edit and update the server's comment field
-        by the server id.
+    def setUp(self):
         """
+        This function perform the four tasks
+         1. Login to test client
+         2. Add the test server
+         3. Get the server
+         4. Connect to server
 
-        srv_grp = config_data['test_server_group']
+        :return: None
+        """
 
-        for srv in config_data['test_server_credentials']:
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
+        # Get the server
+        utils.get_server(self.tester)
+        # Connect to server
+        self.server_connect, self.server_group, self.server_id = \
+            utils.connect_server(self.tester)
+        if len(self.server_connect) == 0:
+            raise Exception("No Server(s) connected to update!!!")
 
-            data = {"name": srv['test_name'],
-                    "host": srv['test_host'],
-                    "port": srv['test_db_port'],
-                    "db": srv['test_maintenance_db'],
-                    "username": srv['test_db_username'],
-                    "role": "",
-                    "sslmode": srv['test_sslmode']}
+    def runTest(self):
+        """ This function will update the server's comment field. """
 
-            url = self.url + str(srv_grp) + "/"
+        data = {
+            "comment":
+                config_data['test_server_update_data']['test_comment'],
+            "id": self.server_id
+        }
 
-            response = self.tester.get(url, data=json.dumps(data),
-                                       content_type='html/json')
+        put_response = self.tester.put(
+            self.url + str(self.server_group) + '/' +
+            str(self.server_id), data=json.dumps(data),
+            content_type='html/json')
+        self.assertEquals(put_response.status_code, 200)
 
-            self.assertTrue(response.status_code, 200)
-            respdata = json.loads(response.data)
+        response_data = json.loads(put_response.data.decode())
+        self.assertTrue(response_data['success'], 1)
 
-            for server in respdata:
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
 
-                url = self.url + str(srv_grp) + "/" + json.dumps(server['id'])
+        :return: None
+        """
 
-                for server in config_data['test_server_update_data']:
-                    data = {"comment": server['test_comment']}
-                    response = self.tester.put(url, data=json.dumps(data),
-                                               content_type='html/json')
-                    self.assertTrue(response.status_code, 200)
-                    respdata = json.loads(response.data)
-                    self.assertTrue(respdata['success'], 1)
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/tests/__init__.py b/web/pgadmin/browser/server_groups/tests/__init__.py
index 9fabed9..7fdd5c7 100644
--- a/web/pgadmin/browser/server_groups/tests/__init__.py
+++ b/web/pgadmin/browser/server_groups/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class SGGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        print ("In SGGenerateTestCase...")
+        return
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/tests/test_sg_add.py b/web/pgadmin/browser/server_groups/tests/test_sg_add.py
deleted file mode 100644
index e70bb65..0000000
--- a/web/pgadmin/browser/server_groups/tests/test_sg_add.py
+++ /dev/null
@@ -1,36 +0,0 @@
-###########################################################################
-#
-# pgAdmin 4 - PostgreSQL Tools
-#
-# Copyright (C) 2013 - 2016, The pgAdmin Development Team
-# This software is released under the PostgreSQL Licence
-#
-###########################################################################
-
-import json
-
-from pgadmin.browser.tests.test_login import LoginTestCase
-from regression.config import config_data
-
-
-class SgNodeTestCase(LoginTestCase):
-    """
-     This class will check available server groups in pgAdmin.
-    """
-
-    priority = 1
-
-    scenarios = [
-        # Fetching the default url for server group node
-        ('Check Server Group Node', dict(url='/browser/server-group/obj/'))
-    ]
-
-    def runTest(self):
-        """This function will check available server groups."""
-
-        i = config_data['test_server_group']
-
-        response = self.tester.get(self.url + str(i), content_type='html/json')
-        self.assertTrue(response.status_code, 200)
-        respdata = json.loads(response.data)
-        self.assertTrue(respdata['id'], i)
diff --git a/web/pgadmin/browser/server_groups/tests/test_sg_get.py b/web/pgadmin/browser/server_groups/tests/test_sg_get.py
new file mode 100644
index 0000000..07bbe96
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/tests/test_sg_get.py
@@ -0,0 +1,48 @@
+###########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+###########################################################################
+
+import json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import config_data
+
+
+class SgNodeTestCase(BaseTestGenerator):
+    """
+     This class will check available server groups in pgAdmin.
+    """
+
+    scenarios = [
+        # Fetching the default url for server group node
+        ('Check Server Group Node', dict(url='/browser/server-group/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function login the test account before running the logout
+        test case
+        """
+
+        utils.login_tester_account(self.tester)
+
+    def runTest(self):
+        """This function will check available server groups."""
+
+        server_group_id = config_data['test_server_group']
+        response = self.tester.get(self.url + str(server_group_id),
+                                   content_type='html/json')
+        self.assertTrue(response.status_code, 200)
+        response_data = json.loads(response.data.decode('utf8'))
+        self.assertTrue(response_data['id'], server_group_id)
+
+    def tearDown(self):
+        """This function logout the test account """
+
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/__init__.py b/web/pgadmin/browser/tests/__init__.py
index 2381efd..3fab6fe 100644
--- a/web/pgadmin/browser/tests/__init__.py
+++ b/web/pgadmin/browser/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class BrowserGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        print ("In BrowserGenerateTestCase...")
+        return
\ No newline at end of file
diff --git a/web/pgadmin/browser/tests/test_change_password.py b/web/pgadmin/browser/tests/test_change_password.py
index dedb7d9..8b47e25 100644
--- a/web/pgadmin/browser/tests/test_change_password.py
+++ b/web/pgadmin/browser/tests/test_change_password.py
@@ -9,19 +9,18 @@
 
 import uuid
 
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
 from regression.config import config_data
+from regression import test_utils as utils
 
 
-class ChangePasswordTestCase(LoginTestCase):
+class ChangePasswordTestCase(BaseTestGenerator):
     """
     This class validates the change password functionality
     by defining change password scenarios; where dict of
     parameters describes the scenario appended by test name.
     """
 
-    priority = 2
-
     scenarios = [
         # This testcase validates invalid confirmation password
         ('TestCase for Validating Incorrect_New_Password', dict(
@@ -48,8 +47,7 @@ class ChangePasswordTestCase(LoginTestCase):
             new_password='', new_password_confirm='',
             respdata='Password not provided')),
 
-        # This testcase validates if current entered password
-        # is incorrect
+        # This testcase validates if current entered password is incorrect
         ('TestCase for Validating Incorrect_Current_Password', dict(
             password=str(uuid.uuid4())[4:8],
             new_password=(config_data['pgAdmin4_login_credentials']
@@ -70,6 +68,7 @@ class ChangePasswordTestCase(LoginTestCase):
                 ['test_new_password']),
             respdata='You successfully changed your password.')),
         ('Reassigning_Password', dict(
+            test_case='reassigning_password',
             password=(config_data['pgAdmin4_login_credentials']
                       ['test_new_password']),
             new_password=(config_data['pgAdmin4_login_credentials']
@@ -81,14 +80,44 @@ class ChangePasswordTestCase(LoginTestCase):
 
     ]
 
+    def setUp(self):
+        """
+        This function login the test account before running the logout
+        test case
+        """
+
+        utils.login_tester_account(self.tester)
+
     def runTest(self):
         """This function will check change password functionality."""
 
+        # Check for 'test_case' exists in self For reassigning the password.
+        # Password gets change in change password test case.
+        if 'test_case' in dir(self):
+            email = \
+                config_data['pgAdmin4_login_credentials'][
+                    'test_login_username']
+            password = \
+                config_data['pgAdmin4_login_credentials'][
+                    'test_new_password']
+            response = self.tester.post('/login', data=dict(
+                email=email, password=password), follow_redirects=True)
+
         response = self.tester.get('/change', follow_redirects=True)
-        self.assertIn('pgAdmin 4 Password Change', response.data)
+        self.assertIn('pgAdmin 4 Password Change', response.data.decode())
+
         response = self.tester.post('/change', data=dict(
             password=self.password,
             new_password=self.new_password,
             new_password_confirm=self.new_password_confirm),
                                     follow_redirects=True)
-        self.assertIn(self.respdata, response.data)
+        self.assertIn(self.respdata, response.data.decode())
+
+    def tearDown(self):
+        """
+        This function logout the test client
+
+        :return: None
+        """
+
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/test_login.py b/web/pgadmin/browser/tests/test_login.py
index 7c2b796..8856700 100644
--- a/web/pgadmin/browser/tests/test_login.py
+++ b/web/pgadmin/browser/tests/test_login.py
@@ -8,9 +8,9 @@
 ##########################################################################
 
 import uuid
-
 from pgadmin.utils.route import BaseTestGenerator
 from regression.config import config_data
+from regression import test_utils as utils
 
 
 class LoginTestCase(BaseTestGenerator):
@@ -20,8 +20,6 @@ class LoginTestCase(BaseTestGenerator):
     describe the scenario appended by test name.
     """
 
-    priority = 0
-
     scenarios = [
         # This test case validates the invalid/incorrect password
         ('TestCase for Checking Invalid_Password', dict(
@@ -67,13 +65,28 @@ class LoginTestCase(BaseTestGenerator):
                    ['test_login_username']),
             password=(config_data['pgAdmin4_login_credentials']
                       ['test_login_password']),
-            respdata='You are currently running version'))
+            respdata='Gravatar image for %s' %
+                     config_data['pgAdmin4_login_credentials']
+                     ['test_login_username']))
     ]
 
+    def setUp(self):
+        pass
+
     def runTest(self):
         """This function checks login functionality."""
 
         response = self.tester.post('/login', data=dict(
             email=self.email, password=self.password),
                                     follow_redirects=True)
-        self.assertIn(self.respdata, response.data)
+        self.assertIn(self.respdata, response.data.decode('utf8'))
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/test_logout.py b/web/pgadmin/browser/tests/test_logout.py
index 8971e72..c2ccf94 100644
--- a/web/pgadmin/browser/tests/test_logout.py
+++ b/web/pgadmin/browser/tests/test_logout.py
@@ -7,38 +7,33 @@
 #
 # ##########################################################################
 
-from pgadmin.browser.tests.test_login import LoginTestCase
-from regression.config import config_data
 
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 
-class LogoutTest(LoginTestCase):
+
+class LogoutTest(BaseTestGenerator):
     """
     This class verifies the logout functionality; provided the user is already
     logged-in. Dictionary parameters define the scenario appended by test
     name.
     """
 
-    priority = 3
-
     scenarios = [
         # This test case validate the logout page
         ('Logging Out', dict(respdata='Redirecting...'))
     ]
 
+    def setUp(self):
+        """
+        This function login the test account before running the logout
+        test case
+        """
+
+        utils.login_tester_account(self.tester)
+
     def runTest(self):
         """This function checks the logout functionality."""
 
         response = self.tester.get('/logout')
-        self.assertIn(self.respdata, response.data)
-
-    def tearDown(self):
-        """
-        Defining tear down class, which will run after each test method execute.
-        Re-logging in as further modules require login.
-        """
-
-        self.tester.post('/login', data=dict(
-            email=(config_data['pgAdmin4_login_credentials']
-                   ['test_login_username']),
-            password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password'])), follow_redirects=True)
+        self.assertIn(self.respdata, response.data.decode('utf8'))
diff --git a/web/pgadmin/browser/tests/test_reset_password.py b/web/pgadmin/browser/tests/test_reset_password.py
index 030b182..26dd80c 100644
--- a/web/pgadmin/browser/tests/test_reset_password.py
+++ b/web/pgadmin/browser/tests/test_reset_password.py
@@ -11,6 +11,7 @@ import uuid
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression.config import config_data
+from regression import test_utils as utils
 
 
 class ResetPasswordTestCase(BaseTestGenerator):
@@ -19,7 +20,6 @@ class ResetPasswordTestCase(BaseTestGenerator):
     scenarios; Each dict parameter describe a scenario appended by
     test name.
     """
-    priority = 1
 
     scenarios = [
         # This test case validates the empty email field
@@ -37,12 +37,29 @@ class ResetPasswordTestCase(BaseTestGenerator):
             ['test_login_username'], respdata='pgAdmin 4'))
     ]
 
+    def setUp(self):
+        """
+        This function login the test account before running the logout
+        test case
+        """
+
+        utils.login_tester_account(self.tester)
+
     def runTest(self):
         """This function checks reset password functionality."""
 
         response = self.tester.get('/reset')
-        self.assertIn('Recover pgAdmin 4 Password', response.data)
+        self.assertIn('Recover pgAdmin 4 Password', response.data.decode())
         response = self.tester.post(
             '/reset', data=dict(email=self.email),
             follow_redirects=True)
-        self.assertIn(self.respdata, response.data)
+        self.assertIn(self.respdata, response.data.decode())
+
+    def tearDown(self):
+        """
+        This function logout the test client
+
+        :return: None
+        """
+
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/utils/route.py b/web/pgadmin/utils/route.py
index fb9de69..a2cd1eb 100644
--- a/web/pgadmin/utils/route.py
+++ b/web/pgadmin/utils/route.py
@@ -52,8 +52,10 @@ class TestsGeneratorRegistry(ABCMeta):
         from werkzeug.utils import find_modules
 
         for module_name in find_modules(pkg, False, True):
-            module = import_module(module_name)
-
+            try:
+                module = import_module(module_name)
+            except ImportError:
+                pass
 
 import six
 
diff --git a/web/regression/README b/web/regression/README
index e0003e4..ef9fd29 100644
--- a/web/regression/README
+++ b/web/regression/README
@@ -40,29 +40,40 @@ General Information
     3. test_server_get.py
     4. test_server_update.py
 
-2) The pgAdmin4 source tree includes a file template for the server configuration
-   named ‘test_config.json.in' in the ‘pgAdmin4/web/regression’ directory. After
-   completing the pgAdmin4 configuration, you must make a working copy of the
-   template called test_config.json before modifying the file contents.
+2) The pgAdmin4 source tree includes 2 different configuration file templates.
+   One file template for the server configuration
+   named ‘test_config.json.in' and another for test configuration named
+   'test_advance_config.json.in' in the ‘pgAdmin4/web/regression’ directory.
+   After completing the pgAdmin4 configuration, you must make a working copy of
+   the templates called test_config.json and test_advance_config.json
+   before modifying the file contents.
 
-	2a) The following command copies the test_config.json.in file, creating a
-	    configuration file named test_config.json
+    2a) The following command copies the test_config.json.in file, creating a
+        configuration file named test_config.json (same way user can copy
+        test_advance_config.json.in file into test_advance_config.json)
 
-            # cp pgadmin4/web/regression/test_config.json.in \
-              pgadmin4/web/regression/test_config.json
+             # cp pgadmin4/web/regression/test_config.json.in \
+               pgadmin4/web/regression/test_config.json
 
-	2b) After creating the server configuration file, add (or modify)
-	    parameter values as per requirements. The configuration
-	    files are owned by root/user. The pgAdmin4 regression framework expects
-	    to find the files in the  directory '/<installation dir>/web/regression/'.
-	    If you move the file to another location, you must create a symbolic link
-	    that specifies the new location.
+    2b) After creating the server and test configuration file, add (or modify)
+        parameter values as per requirements. The configuration
+        files are owned by root/user. The pgAdmin4 regression framework expects
+        to find the files in the  directory '/<installation dir>/web/regression/'.
+        If you move the file to another location, you must create a symbolic
+        link that specifies the new location.
 
-	2c) Specifying Server Configuration file:
+    2c) Specifying Server Configuration file:
+
+        server details and connection properties as per their local setup. The
+        test_config file is in json format and property values are
+        case-sensitive.
+
+    2d) Specifying the Test Configuration file:
+
+        The user can add/change test data as per their need. The
+        test_advance_config file is in json format and property values are
+        case-sensitive.
 
-	    The user can use the parameters in the configuration file to specify the
-	    server details and connection properties as per their local setup. The
-	    test_config file is in json format and property values are case-sensitive.
 
 Test Data Details
 -----------------
@@ -92,5 +103,18 @@ Execution:
   and registered automatically by its module name in
   'pgadmin4/web/pgadmin/utils/test.py' file.
 
-- Execute test framework run 'regression/testsuite.py' file.
+- As the test framework is modular and dynamically locates the tests
+  package, We can now executes test framework node wise
+
+- Execute test framework for all nodes
+     run 'regression/testsuite.py --pkg all'
+
+- Execute test framework for single node at a time
+
+     Example 1) Run test framework for 'browser' node
+     run 'regression/testsuite.py --pkg browser'
+
+     Example 2) Run test framework for 'database' node
+     run 'regression/testsuite.py --pkg browser.server_groups.servers.databases'
+
 
diff --git a/web/regression/config.py b/web/regression/config.py
index bef65fb..f48eade 100644
--- a/web/regression/config.py
+++ b/web/regression/config.py
@@ -14,3 +14,8 @@ root = os.path.dirname(os.path.realpath(__file__))
 
 with open(root + '/test_config.json') as data_file:
     config_data = json.load(data_file)
+
+with open(root + '/test_advance_config.json') as data_file:
+    advance_config_data = json.load(data_file)
+
+pickle_path = os.path.join(root, 'parent_id.pkl')
diff --git a/web/regression/test_advance_config.json.in b/web/regression/test_advance_config.json.in
new file mode 100644
index 0000000..bcb867c
--- /dev/null
+++ b/web/regression/test_advance_config.json.in
@@ -0,0 +1,105 @@
+{
+  "test_add_database_data": [
+   {
+    "test_privileges_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "C",
+            "privilege": true,
+            "with_grant": true
+          },
+          {
+            "privilege_type": "T",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_conn_limit": -1,
+    "test_owner": "postgres",
+    "test_fun_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "X",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_seq_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "r",
+            "privilege": true,
+            "with_grant": false
+          },
+          {
+            "privilege_type": "w",
+            "privilege": true,
+            "with_grant": false
+          },
+          {
+            "privilege_type": "U",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_tbl_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "a",
+            "privilege": true,
+            "with_grant": true
+          },
+          {
+            "privilege_type": "r",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_type_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "U",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_encoding": "UTF8",
+    "test_name": "test_db_automation",
+    "test_privileges": [],
+    "test_securities": [],
+    "test_variables": []
+  }
+ ],
+
+  "test_db_update_data": [
+  {
+      "test_comment": "This is db update comment"
+  }
+ ]
+
+}
\ No newline at end of file
diff --git a/web/regression/test_nodes.py b/web/regression/test_nodes.py
new file mode 100644
index 0000000..0fa4695
--- /dev/null
+++ b/web/regression/test_nodes.py
@@ -0,0 +1,40 @@
+# ##################################################################
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from regression.config import config_data
+from regression.test_utils import get_ids
+
+
+def test_getnodes(node=None):
+    # Connect to server and database.
+
+    if not node:
+        return None
+
+    all_id = get_ids()
+
+    server_id = all_id["sid"][0]
+    db_id = all_id["did"][0]
+    srv_grp = config_data['test_server_group']
+
+    # Connect to server
+    response = node.tester.post('browser/server/connect/{0}/{1}'.format(
+        srv_grp, server_id), data = dict(
+        password=config_data['test_server_credentials'][0]['test_db_password']),
+        follow_redirects = True)
+
+    # Connect to database
+    con_response = node.tester.post(
+        'browser/database/connect/{0}/{1}/{2}'.format(
+            srv_grp, server_id, db_id), follow_redirects = True)
+
+    db_con = json.loads(con_response.data.decode())
+
+    return db_con
\ No newline at end of file
diff --git a/web/regression/test_utils.py b/web/regression/test_utils.py
new file mode 100644
index 0000000..900f405
--- /dev/null
+++ b/web/regression/test_utils.py
@@ -0,0 +1,290 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import os
+import pickle
+import json
+import uuid
+
+import config
+from regression.config import config_data, advance_config_data
+
+SERVER_URL = '/browser/server/obj/'
+SERVER_CONNECT_URL = 'browser/server/connect/'
+DATABASE_CONNECT_URL = '/browser/database/obj/'
+
+
+def get_ids(url=config.APP_ROOT + '/regression/parent_id.pkl'):
+    """
+    This function read the parent node's id and return it
+
+    :param url: file path from which it will red the ids
+    :type url: str
+    :return: node ids
+    :rtype: dict
+    """
+
+    output = open(url, 'rb')
+    ids = pickle.load(output)
+    output.close()
+
+    return ids
+
+
+def login_tester_account(tester):
+    """
+    This function login the test account using credentials mentioned in
+    config file
+
+    :param tester: test client
+    :type tester: flask test client object
+    :return: None
+    """
+
+    email = \
+        config_data['pgAdmin4_login_credentials']['test_login_username']
+    password = \
+        config_data['pgAdmin4_login_credentials']['test_login_password']
+    response = tester.post('/login', data=dict(
+        email=email, password=password), follow_redirects=True)
+
+
+def logout_tester_account(tester):
+    """
+    This function logout the test account
+
+    :param tester: test client
+    :type tester: flask test client object
+    :return: None
+    """
+
+    response = tester.get('/logout')
+
+
+def get_config_data():
+    """
+    This function get the data related to server group and database
+    like db name, host, port and username etc.
+
+    :return: server_group, db_data, pickle_id_dict
+    :rtype: server_group:dict, db_data:list, pickle_id_dict:dict
+    """
+
+    db_data = []
+
+    pickle_id_dict = {
+        "sid": [],  # server
+        "did": [],  # database
+        "lrid": [],  # login role
+        "tsid": [],  # tablspace
+        "cid": [],  # cast
+        "eid": [],  # extention
+        "lid": [12397],  # language
+        "scid": [],  # schema
+        "tfnid": [],  # trigger function
+        "etid": [],  # event trigger
+        "coid": [],  # collation
+        "fid": [],  # FDW
+        "doid": [],  # Domain
+        "seid": [],  # Sequence
+        "tid": [],  # table
+        "vid": [],  # view
+        "mvid": [],  # mview
+        "fsid": [],  # foreign server
+        "umid": [],  # User mapping
+        "foid": []  # foreign table
+    }
+
+    server_group = config_data['test_server_group']
+
+    for srv in config_data['test_server_credentials']:
+        data = {"name": srv['test_name'],
+                "comment": "",
+                "host": srv['test_host'],
+                "port": srv['test_db_port'],
+                "db": srv['test_maintenance_db'],
+                "username": srv['test_db_username'],
+                "role": "",
+                "sslmode": srv['test_sslmode']}
+        db_data.append(data)
+    return server_group, db_data, pickle_id_dict
+
+
+def write_parent_id(response_data, pickle_id_dict):
+    """
+    This function writes the server's details to file parent_id.pkl
+
+    :param response_data: server's data
+    :type response_data: list of dictionary
+    :param pickle_id_dict: contains ids of server,database,tables etc.
+    :type pickle_id_dict: dict
+    :return: None
+    """
+
+    server_id = response_data['node']['_id']
+    if os.path.isfile(config.APP_ROOT + '/regression/parent_id.pkl'):
+        existed_server_id = open(
+            config.APP_ROOT + '/regression/parent_id.pkl', 'rb')
+        pickle_id_dict = pickle.load(existed_server_id)
+
+    pickle_id_dict["sid"].append(server_id)
+    output = open(config.APP_ROOT + '/regression/parent_id.pkl', 'wb')
+    pickle.dump(pickle_id_dict, output)
+    output.close()
+
+
+def write_db_parent_id(response_data):
+    """
+    This function writes the server and database related data like server
+    name, server id , database name, database id etc.
+
+    :param response_data: server and databases details
+    :type response_data: dict
+    :return: None
+    """
+
+    db_id = response_data['node']['_id']
+    if os.path.isfile(config.APP_ROOT + '/regression/parent_id.pkl'):
+        existing_server_id = open(
+            config.APP_ROOT + '/regression/parent_id.pkl', 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+
+        pickle_id_dict["did"].append(db_id)
+
+        db_output = open(
+            config.APP_ROOT + '/regression/parent_id.pkl', 'wb')
+        pickle.dump(pickle_id_dict, db_output)
+        db_output.close()
+
+
+def delete_parent_id_file():
+    """
+    This function deletes the file parent_id.pkl which contains server and
+    database details
+
+    :return: None
+    """
+
+    if os.path.isfile(config.APP_ROOT + '/regression/parent_id.pkl'):
+        os.remove(config.APP_ROOT + '/regression/parent_id.pkl')
+
+
+def add_server(tester):
+    """
+    This function add the server in the existing server group
+
+    :param tester: test object
+    :type tester: flask test object
+    :return:None
+    """
+
+    server_group, db_data, pickle_id_dict = get_config_data()
+    url = "{0}{1}/".format(SERVER_URL, server_group)
+    response = tester.post(url, data=json.dumps(db_data[0]),
+                           content_type='html/json')
+    response_data = json.loads(response.data.decode())
+    write_parent_id(response_data, pickle_id_dict)
+
+
+def get_server(tester):
+    """
+    This function gets the added serer details
+
+    :param tester: test client object
+    :type tester: flask test object
+    :return: response_data
+    :rtype: list
+    """
+
+    all_id = get_ids()
+    server_id = all_id["sid"][0]
+    server_group = config_data['test_server_group']
+
+    response = tester.get(SERVER_URL + str(server_group) + '/' +
+                          str(server_id),
+                          follow_redirects=True)
+    response_data = json.loads(response.data.decode())
+    return response_data
+
+
+def connect_server(tester):
+    """
+    This function used to connect added server
+
+    :param tester:test client object
+    :type tester: flask test object
+    :return: server_connect, server_group, server_id
+    :rtype: server_connect:dict, server_group:dict, server_id:str
+    """
+
+    srv_id = get_ids()
+    server_id = srv_id["sid"][0]
+    server_group = config_data['test_server_group']
+    response = tester.post(SERVER_CONNECT_URL + str(server_group) +
+                           '/' + server_id,
+                           data=dict(
+                               password=config_data
+                               ['test_server_credentials'][0]
+                               ['test_db_password']),
+                           follow_redirects=True)
+    server_connect = json.loads(response.data.decode())
+    connect_database(tester, server_connect, server_id, server_group)
+    return server_connect, server_group, server_id
+
+
+def connect_database(tester, server_connect, server_id, server_group):
+    """
+    This function is used to connect database and writes it's details to
+    file 'parent_id.pkl'
+
+    :param tester: test client object
+    :type tester: flask test client object
+    :param server_connect: server's data
+    :type server_connect: dict
+    :param server_id: server id
+    :type server_id: str
+    :param server_group: server group name
+    :type server_group: str
+    :return: None
+    """
+
+    if server_connect['data']['connected']:
+        data = {
+            "datacl": advance_config_data['test_add_database_data'][0]
+            ['test_privileges_acl'],
+            "datconnlimit": advance_config_data
+            ['test_add_database_data'][0]['test_conn_limit'],
+            "datowner": advance_config_data
+            ['test_add_database_data'][0]['test_owner'],
+            "deffuncacl": advance_config_data
+            ['test_add_database_data'][0]['test_fun_acl'],
+            "defseqacl": advance_config_data
+            ['test_add_database_data'][0]['test_seq_acl'],
+            "deftblacl": advance_config_data
+            ['test_add_database_data'][0]['test_tbl_acl'],
+            "deftypeacl": advance_config_data
+            ['test_add_database_data'][0]['test_type_acl'],
+            "encoding": advance_config_data
+            ['test_add_database_data'][0]['test_encoding'],
+            "name": str(uuid.uuid4())[1:8],
+            "privileges": advance_config_data
+            ['test_add_database_data'][0]['test_privileges'],
+            "securities": advance_config_data
+            ['test_add_database_data'][0]['test_securities'],
+            "variables": advance_config_data
+            ['test_add_database_data'][0]['test_variables']
+        }
+
+        db_response = tester.post(
+            DATABASE_CONNECT_URL + str(server_group) + "/" + server_id + "/",
+            data=json.dumps(data),
+            content_type='html/json')
+        response_data = json.loads(db_response.data.decode())
+        write_db_parent_id(response_data)
diff --git a/web/regression/testsuite.py b/web/regression/testsuite.py
index 75d437b..cf824b9 100644
--- a/web/regression/testsuite.py
+++ b/web/regression/testsuite.py
@@ -10,70 +10,147 @@
 """ This file collect all modules/files present in tests directory and add
 them to TestSuite. """
 
+import argparse
 import os
 import sys
 import unittest
+import logging
 
 from testscenarios.scenarios import generate_scenarios
 
-# We need to include the root directory in sys.path to ensure that we can
-# find everything we need when running in the standalone runtime.
-current_path = os.path.dirname(os.path.realpath(__file__))
-root = os.path.dirname(current_path)
+CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
 
-if sys.path[0] != root:
-    sys.path.insert(0, root)
 
-from pgadmin import create_app
-import config
+def create_pgadmin_app():
+    """
+    This function creates the pgadmin app for testing
 
-# Get the config database schema version. We store this in pgadmin.model
-# as it turns out that putting it in the config files isn't a great idea
-from pgadmin.model import SCHEMA_VERSION
-config.SETTINGS_SCHEMA_VERSION = SCHEMA_VERSION
+    :return: test client
+    :rtype: test app object
+    """
 
-# Create the app!
-app = create_app()
+    # Set sys path to current directory so that we can import pgadmin package
+    root = os.path.dirname(CURRENT_PATH)
+    if sys.path[0] != root:
+        sys.path.insert(0, root)
 
-# Disabling Cross-site request forgery(CSRF token) for testing purpose.
-# CSRF prevent session against malicious Web site, or end users who wants to
-# execute unwanted actions.
-app.config['WTF_CSRF_ENABLED'] = False
+    from pgadmin import create_app
+    import config
 
-from pgadmin.utils.route import TestsGeneratorRegistry
+    # Get the config database schema version. We store this in pgadmin.model
+    # as it turns out that putting it in the config files isn't a great idea
+    from pgadmin.model import SCHEMA_VERSION
 
-# Registry will load all the testcases/modules from pgadmin path those are
-# register as BaseTestGenerator.
-TestsGeneratorRegistry.load_generators('pgadmin')
+    config.SETTINGS_SCHEMA_VERSION = SCHEMA_VERSION
 
-# Create test client
-# werkzeug provides a test client which gives a simple interface to the
-# application. We can trigger test request to the application.
-test_client = app.test_client()
+    # Create the app
+    app = create_app()
+    app.config['WTF_CSRF_ENABLED'] = False
+    test_app_client = app.test_client()
 
+    return test_app_client
 
-def suite():
-    """ Defining test suite which will execute all the testcases present in
-    tests directory according to set priority."""
 
-    pgadmin_suite = unittest.TestSuite()
+def get_suite(arguments, test_app_client):
+    """
+     This function loads the all modules in the tests directory into testing
+     environment.
+
+    :param arguments: this is command line arguments for module name to
+    which test suite will run
+    :type arguments: str
+    :param test_app_client: test client
+    :type test_app_client: pgadmin app object
+    :return pgadmin_suite: test suite with test cases
+    :rtype: TestSuite
+    """
+
+    from pgadmin.utils.route import TestsGeneratorRegistry
 
     modules = []
+    pgadmin_suite = unittest.TestSuite()
+
+    # Load the test modules which are in given package(i.e. arguments.pkg)
+    if arguments.pkg == "all":
+        TestsGeneratorRegistry.load_generators('pgadmin')
+    else:
+        TestsGeneratorRegistry.load_generators('pgadmin.{}.tests'.format(
+            arguments.pkg))
 
+    # Get the each test module and add into list
     for key, klass in TestsGeneratorRegistry.registry.items():
         gen = klass
+        modules.append(gen)
 
-        modules.insert(gen.priority, gen)
-
-    for m in modules:
-        obj = m()
-        obj.setTestClient(test_client)
+    # Set the test client to each module & generate the scenarios
+    for module in modules:
+        obj = module()
+        obj.setTestClient(test_app_client)
         scenario = generate_scenarios(obj)
         pgadmin_suite.addTests(scenario)
 
     return pgadmin_suite
 
 
+def add_arguments():
+    """
+    This function parse the command line arguments(project's package name
+    e.g. browser) & add into parser
+
+    :return args: command line argument for pgadmin's package name
+    :rtype: argparse namespace
+    """
+
+    parser = argparse.ArgumentParser(description='Test suite for pgAdmin4')
+    parser.add_argument('--pkg', help='Executes the test cases of particular'
+                                      ' package')
+    arg = parser.parse_args()
+
+    return arg
+
+
+class StreamToLogger(object):
+    def __init__(self, logger, log_level=logging.INFO):
+        self.terminal = sys.stderr
+        self.logger = logger
+        self.log_level = log_level
+        self.linebuf = ''
+
+    def write(self, buf):
+        """
+        This function writes the log in the logger file as well as on console
+
+        :param buf: log message
+        :type buf: str
+        :return: None
+        """
+
+        self.terminal.write(buf)
+        for line in buf.rstrip().splitlines():
+            self.logger.log(self.log_level, line.rstrip())
+
+    def flush(self):
+        pass
+
+
 if __name__ == '__main__':
-    suite = suite()
-    tests = unittest.TextTestRunner(descriptions=True, verbosity=2).run(suite)
+    # Set basic logging configuration for log file
+    logging.basicConfig(level=logging.DEBUG,
+                        format='%(asctime)s:%(levelname)s:%(name)s:%(message)s',
+                        filename="logger.log",
+                        filemode='w'
+                        )
+
+    # Create logger to write log in the logger file with on console
+    stderr_logger = logging.getLogger('STDERR')
+    sys.stderr = StreamToLogger(stderr_logger, logging.ERROR)
+
+    # Create the pgadmin app
+    test_client = create_pgadmin_app()
+    args = add_arguments()
+    suite = get_suite(args, test_client)
+    tests = unittest.TextTestRunner(stream=sys.stderr, descriptions=True,
+                                    verbosity=2).run(suite)
+
+    print("\n\n Please check output in file: logger.log placed at ",
+          CURRENT_PATH)


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-15 12:53  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Dave Page @ 2016-07-15 12:53 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi

On Mon, Jul 11, 2016 at 2:16 PM, Navnath Gadakh <
[email protected]> wrote:

> Hi Dave,
> PFA updated patch for modular API test cases.
>
> On Mon, Jul 11, 2016 at 5:11 PM, Dave Page <[email protected]>
> wrote:
>
>>
>>
>> On Fri, Jul 8, 2016 at 2:30 PM, Navnath Gadakh <
>> [email protected]> wrote:
>>
>>>
>>> Hi Dave,
>>>
>>> PFA patch for modular API test cases.
>>>
>>> Kindly, review the same and let me know for any modification.
>>>
>>
>> Please re-create the patch so that it doesn't revert various changes made
>> to config.py etc. over the last couple of weeks.
>>
>
>   config.py file was not updated at my end, I have updated it in the
> current patch.  I have also added code related to advance test data
> configuration which was created by Priyanka (Seprated the test data
> configuration files).
>
>
>> What is the patch for? Is it fixing issues in Priyanka's last patch, or
>> something else?
>> This patch is for -
>> 1. Now we can run testsuite node/module wise(like for browser only, for
>> databases only)  OR for all nodes/modules
>> 2. I have modified the existing functionality for testsuite and all test
>> case classes (Made all test cases independently runnable, removed
>> the priority logic).
>>
>
>
    For more details please refer the file 'regression/README'.
>

When running all tests, I get:

...
...
 <Rule '//static/<filename>' (HEAD, OPTIONS, GET) -> redirects.static>,
 <Rule '/backup/<filename>' (HEAD, OPTIONS, GET) -> backup.static>,
 <Rule '/reset/<token>' (HEAD, POST, OPTIONS, GET) ->
security.reset_password>,
 <Rule '/about/<filename>' (HEAD, OPTIONS, GET) -> about.static>])
Traceback (most recent call last):
  File "regression/testsuite.py", line 151, in <module>
    suite = get_suite(args, test_client)
  File "regression/testsuite.py", line 75, in get_suite
    TestsGeneratorRegistry.load_generators('pgadmin')
  File "/Users/dpage/git/pgadmin4/web/pgadmin/utils/route.py", line 56, in
load_generators
    module = import_module(module_name)
  File
"/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py",
line 37, in import_module
    __import__(name)
  File
"/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py",
line 14, in <module>
    from regression import test_utils as utils
  File "/Users/dpage/git/pgadmin4/web/regression/test_utils.py", line 23,
in <module>
    def get_ids(url=config.APP_ROOT + '/regression/parent_id.pkl'):
AttributeError: 'module' object has no attribute 'APP_ROOT'

That's not overly surprising, as we don't have an APP_ROOT setting in the
config (nor should we - it should be calculated dynamically). Please fix,
and remember to test your patches against a clean copy of the git tree in
the future!

Thanks!

-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-18 12:45  Navnath Gadakh <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-07-18 12:45 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,

  Please find the revised patch for unit tests of pgAdmin4 APIs.

This patch includes-

   1.

   test_advance_config.json(for user it’s test_advance_config.json.in) for
   advance test configuration for database/server(Priyanka was working on this)
   2.

   test_config.json(for user it’s test_config_json.in) for basic
   credentials data for database/server
   3.

   From now onward we can execute test cases node wise/package wise. I have
   slightly modified the way of running the testsuite. We used the command
   line arguments(pkg) which denotes for which package testsuite going to
   run.


          Run the testsuite for all packages by following command

               Python regression/testsuite.py --pkg all

      Here, ‘all’ means for all python
packages(i.e.browser,server_groups,server,

                            databases etc. which are same names in project
directory structure)

               This will find the ‘tests’ directory in each package &
execute the test cases.



          Run the testsuite for single package by following command

      Python regression/testsuite.py --pkg browser (this execute the tests
in ‘browser’ package only)

       Python regression/testsuite.py --pkg
browser.server_groups.servers.databases (this execute the tests in
‘databases’ package only)

  4.  Logger file. Which include the detailed output of the testsuite.
Testsuite also prints the test summary on the console.

    5.  Previously, we set the priority to each test case. In this patch
priority logic is removed as there is no need to set priority.

    6. Resolution of AttributeError for attribute 'APP_ROOT'(Which is
mentioned by you in a previous email)

Note: You might get ‘AttributeError’ while running this patch on Python 3.4
(I have raised this bug in RM(#1464)), But still you can run the testsuite.
It will run on Python 2.7 without error.


On Fri, Jul 15, 2016 at 6:23 PM, Dave Page <[email protected]>
wrote:

> Hi
>
> On Mon, Jul 11, 2016 at 2:16 PM, Navnath Gadakh <
> [email protected]> wrote:
>
>> Hi Dave,
>> PFA updated patch for modular API test cases.
>>
>> On Mon, Jul 11, 2016 at 5:11 PM, Dave Page <[email protected]>
>> wrote:
>>
>>>
>>>
>>> On Fri, Jul 8, 2016 at 2:30 PM, Navnath Gadakh <
>>> [email protected]> wrote:
>>>
>>>>
>>>> Hi Dave,
>>>>
>>>> PFA patch for modular API test cases.
>>>>
>>>> Kindly, review the same and let me know for any modification.
>>>>
>>>
>>> Please re-create the patch so that it doesn't revert various changes
>>> made to config.py etc. over the last couple of weeks.
>>>
>>
>>   config.py file was not updated at my end, I have updated it in the
>> current patch.  I have also added code related to advance test data
>> configuration which was created by Priyanka (Seprated the test data
>> configuration files).
>>
>>
>>> What is the patch for? Is it fixing issues in Priyanka's last patch, or
>>> something else?
>>> This patch is for -
>>> 1. Now we can run testsuite node/module wise(like for browser only, for
>>> databases only)  OR for all nodes/modules
>>> 2. I have modified the existing functionality for testsuite and all test
>>> case classes (Made all test cases independently runnable, removed
>>> the priority logic).
>>>
>>
>>
>     For more details please refer the file 'regression/README'.
>>
>
> When running all tests, I get:
>
> ...
> ...
>  <Rule '//static/<filename>' (HEAD, OPTIONS, GET) -> redirects.static>,
>  <Rule '/backup/<filename>' (HEAD, OPTIONS, GET) -> backup.static>,
>  <Rule '/reset/<token>' (HEAD, POST, OPTIONS, GET) ->
> security.reset_password>,
>  <Rule '/about/<filename>' (HEAD, OPTIONS, GET) -> about.static>])
> Traceback (most recent call last):
>   File "regression/testsuite.py", line 151, in <module>
>     suite = get_suite(args, test_client)
>   File "regression/testsuite.py", line 75, in get_suite
>     TestsGeneratorRegistry.load_generators('pgadmin')
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/utils/route.py", line 56, in
> load_generators
>     module = import_module(module_name)
>   File
> "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py",
> line 37, in import_module
>     __import__(name)
>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py",
> line 14, in <module>
>     from regression import test_utils as utils
>   File "/Users/dpage/git/pgadmin4/web/regression/test_utils.py", line 23,
> in <module>
>     def get_ids(url=config.APP_ROOT + '/regression/parent_id.pkl'):
> AttributeError: 'module' object has no attribute 'APP_ROOT'
>
> That's not overly surprising, as we don't have an APP_ROOT setting in the
> config (nor should we - it should be calculated dynamically). Please fix,
> and remember to test your patches against a clean copy of the git tree in
> the future!
>
> Thanks!
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>



-- 
Thanks,
Navnath Gadakh
Software Engineer
EnterpriseDB Corporation
Mobile: +91 9975389878


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [text/x-patch] pgadmin_unittest_modular.patch (63.2K, 3-pgadmin_unittest_modular.patch)
  download | inline diff:
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/tests/__init__.py
new file mode 100644
index 0000000..aa01297
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/__init__.py
@@ -0,0 +1,15 @@
+# ##########################################################################
+#
+# #pgAdmin 4 - PostgreSQL Tools
+#
+# #Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# #This software is released under the PostgreSQL Licence
+#
+# ##########################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class DatabaseCreateTestCase(BaseTestGenerator):
+    def runTest(self):
+        return
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
new file mode 100644
index 0000000..14b9749
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
@@ -0,0 +1,74 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+import uuid
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import advance_config_data
+
+
+class DatabaseAddTestCase(BaseTestGenerator):
+    """
+    This class will check server group node present on the object browser's
+    tree node by response code.
+    """
+
+    scenarios = [
+        # Fetching default URL for database node.
+        ('Check Databases Node URL', dict(url='/browser/database/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function perform the two tasks
+         1. Login to test client
+         2. Add the test server
+
+        :return: None
+        """
+
+        utils.login_tester_account(self.tester)
+        # Add the server
+        utils.add_server(self.tester)
+
+    def runTest(self):
+        """ This function will add database under 1st server of tree node. """
+
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester)
+
+        # Store db id. Which is use to delete in tearDown()
+        self.db_id = ''
+        for server_connect, server_id in zip(server_connect_response,
+                                             server_ids):
+            if server_connect['data']['connected']:
+                data = utils.get_db_data(server_connect)
+                db_response = self.tester.post(self.url + str(server_group) +
+                                               "/" + server_id + "/",
+                                               data=json.dumps(data),
+                                               content_type='html/json')
+                self.assertTrue(db_response.status_code, 200)
+                response_data = json.loads(db_response.data.decode('utf-8'))
+                utils.write_db_parent_id(response_data)
+                self.db_id = response_data['node']['_id']
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_database(self.tester, self.db_id)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
new file mode 100644
index 0000000..46c59e4
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
@@ -0,0 +1,73 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import config_data
+from regression.test_utils import get_ids, test_getnodes
+
+
+class DatabaseDeleteTestCase(BaseTestGenerator):
+    """ This class will delete the database under last added server. """
+
+    scenarios = [
+        # Fetching default URL for database node.
+        ('Check Databases Node URL', dict(url='/browser/database/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function perform the three tasks
+         1. Login to test client
+         2. Add the test server
+         3. Connect to server
+
+        :return: None
+        """
+
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
+        # Secondly, connect to server/database
+        utils.connect_server(self.tester)
+
+    def runTest(self):
+        """ This function will delete the database."""
+
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+
+        # TODO: Need to modify the code , to delete the databases for all
+        # TODO: servers. Currently it delete only one database.
+        db_id = all_id["did"][0]
+        db_con = test_getnodes(self.tester)
+        if len(db_con) == 0:
+            raise Exception("No database(s) to delete!!!")
+        for server_id in server_ids:
+            response = self.tester.delete(self.url + str(srv_grp) + '/' +
+                                          str(server_id) + '/' + str(db_id),
+                                          follow_redirects=True)
+
+            response_data = json.loads(response.data.decode('utf-8'))
+            self.assertTrue(response_data['success'], 1)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
new file mode 100644
index 0000000..3edd6b8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
@@ -0,0 +1,72 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import config_data
+from regression.test_utils import get_ids, test_getnodes
+
+
+class DatabasesGetTestCase(BaseTestGenerator):
+    """
+    This class will fetch database added under last added server.
+    """
+
+    scenarios = [
+        # Fetching default URL for database node.
+        ('Check Databases Node URL', dict(url='/browser/database/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function perform the three tasks
+         1. Login to test client
+         2. Add the test server
+         3. Connect to server
+
+        :return: None
+        """
+
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
+        # Secondly, connect to server/database
+        utils.connect_server(self.tester)
+
+    def runTest(self):
+        """ This function will fetch added database. """
+
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+
+        # TODO: Code is remaining to get all databases of all servers
+        self.db_id = all_id["did"][0]
+        srv_grp = config_data['test_server_group']
+
+        for server_id in server_ids:
+            db_con = test_getnodes(self.tester)
+            if db_con["info"] == "Database connected.":
+                response = self.tester.get(self.url + str(srv_grp) + '/' +
+                                           str(server_id) + '/' + str(
+                    self.db_id),
+                                           follow_redirects=True)
+                self.assertEquals(response.status_code, 200)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_database(self.tester, self.db_id)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
new file mode 100644
index 0000000..347e684
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
@@ -0,0 +1,79 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import config_data, advance_config_data
+from regression.test_utils import get_ids, test_getnodes
+
+
+class DatabasesUpdateTestCase(BaseTestGenerator):
+    """
+    This class will update the database under last added server.
+    """
+
+    scenarios = [
+        # Fetching default URL for database node.
+        ('Check Databases Node', dict(url='/browser/database/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function perform the three tasks
+         1. Login to test client
+         2. Add the test server
+         3. Connect to server
+
+        :return: None
+        """
+
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
+        # Secondly, connect to server/database
+        utils.connect_server(self.tester)
+
+    def runTest(self):
+        """ This function will update the comments field of database."""
+
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+
+        # TODO: Need to modify the code , to delete the databases for all
+        # TODO: servers. Currently it delete only one database.
+        db_id = all_id["did"][0]
+        test_getnodes(self.tester)
+
+        data = {
+            "comments": advance_config_data["test_db_update_data"][0]
+            ["test_comment"],
+            "id": db_id
+        }
+
+        for server_id in server_ids:
+            put_response = self.tester.put(self.url + str(srv_grp) + '/' +
+                                           str(server_id) + '/' + str(db_id),
+                                           data=json.dumps(data),
+                                           follow_redirects=True)
+            self.assertEquals(put_response.status_code, 200)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/tests/__init__.py
index 28cdb94..55a3a17 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class ServerGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        print ("In ServerGenerateTestCase...")
+        return
\ No newline at end of file
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 0af13d3..847b1b6 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
@@ -9,45 +9,50 @@
 
 import json
 
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 from regression.config import config_data
+from regression.test_utils import get_ids
 
 
-class ServersAddTestCase(LoginTestCase):
-    """
-    This class will add the servers under default server group and verify with
-    server's name.
-    """
-
-    priority = 4
+class ServersAddTestCase(BaseTestGenerator):
+    """ This class will add the servers under default server group. """
 
     scenarios = [
         # Fetch the default url for server object
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def runTest(self):
+    def setUp(self):
         """
-        This function will add the server under default server group.
-        Verify the added server with response code as well as server name.
+        This function login the test account before running the logout
+        test case
         """
 
-        srv_grp = config_data['test_server_group']
-
-        for srv in config_data['test_server_credentials']:
-            data = {"name": srv['test_name'],
-                    "comment": "",
-                    "host": srv['test_host'],
-                    "port": srv['test_db_port'],
-                    "db": srv['test_maintenance_db'],
-                    "username": srv['test_db_username'],
-                    "role": "",
-                    "sslmode": srv['test_sslmode']}
+        utils.login_tester_account(self.tester)
 
-            url = self.url + str(srv_grp) + "/"
+    def runTest(self):
+        """ This function will add the server under default server group."""
 
-            response = self.tester.post(url, data=json.dumps(data),
+        server_group, config_data, pickle_id_dict = utils.get_config_data()
+        for server_data in config_data:
+            url = "{0}{1}/".format(self.url, server_group)
+            response = self.tester.post(url, data=json.dumps(server_data),
                                         content_type='html/json')
+
             self.assertTrue(response.status_code, 200)
-            respdata = json.loads(response.data)
-            self.assertTrue(respdata['node']['label'], srv['test_name'])
+
+            response_data = json.loads(response.data.decode())
+            utils.write_parent_id(response_data, pickle_id_dict)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
index 329d74f..4f312cf 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
@@ -9,49 +9,59 @@
 
 import json
 
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 from regression.config import config_data
+from regression.test_utils import get_ids
 
 
-class ServersDeleteTestCase(LoginTestCase):
-    """
-    This class will check server node present on the object browser's tree node
-    by response code.
-    """
-    priority = 7
+class ServerDeleteTestCase(BaseTestGenerator):
+    """ This class will delete the last server present under tree node."""
 
     scenarios = [
         # Fetching the default url for server node
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def runTest(self):
+    def setUp(self):
         """
-        This function will get all available servers under object browser
-        and delete the servers using server id.
+        This function perform the two tasks
+         1. Login to test client
+         2. Add the test server
+
+        :return: None
         """
 
-        srv_grp = config_data['test_server_group']
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
 
-        for srv in config_data['test_server_credentials']:
+    def runTest(self):
+        """ This function will get all available servers under object browser
+        and delete the last server using server id."""
 
-            data = {"name": srv['test_name'],
-                    "host": srv['test_host'],
-                    "port": srv['test_db_port'],
-                    "db": srv['test_maintenance_db'],
-                    "username": srv['test_db_username'],
-                    "role": "",
-                    "sslmode": srv['test_sslmode']}
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
 
-            url = self.url + str(srv_grp) + "/"
+        url = self.url + str(srv_grp) + "/"
+        if len(server_ids) == 0:
+            raise Exception("No server(s) to delete!!!")
 
-            response = self.tester.get(url, data=json.dumps(data),
-                                       content_type='html/json')
+        # Call api to delete the servers
+        for server_id in server_ids:
+            response = self.tester.delete(url + str(server_id))
             self.assertTrue(response.status_code, 200)
-            respdata = json.loads(response.data)
+            response_data = json.loads(response.data.decode())
+            self.assertTrue(response_data['success'], 1)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
 
-            for server in respdata:
-                response = self.tester.delete(url + json.dumps(server['id']))
-                self.assertTrue(response.status_code, 200)
-                respdata = json.loads(response.data)
-                self.assertTrue(respdata['success'], 1)
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
index 050843e..6356a6b 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
@@ -7,43 +7,55 @@
 #
 # ##########################################################################
 
-import json
-
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 from regression.config import config_data
+from regression.test_utils import get_ids
 
 
-class ServersGetTestCase(LoginTestCase):
+class ServersGetTestCase(BaseTestGenerator):
     """
-    This class will check server node present on the object browser's tree node
+    This class will fetch added servers under default server group
     by response code.
     """
 
-    priority = 5
-
     scenarios = [
         # Fetch the default url for server node
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def runTest(self):
+    def setUp(self):
         """
-        This function will get all available servers present under
-        object browser.
+        This function perform the two tasks
+         1. Login to test client
+         2. Add the test server
+
+        :return: None
         """
 
+        utils.login_tester_account(self.tester)
+        utils.add_server(self.tester)
+
+    def runTest(self):
+        """ This function will fetch the added servers to object browser. """
+
+        all_id = get_ids()
+        server_ids = all_id["sid"]
         srv_grp = config_data['test_server_group']
 
-        for srv in config_data['test_server_credentials']:
-            data = {"name": srv['test_name'],
-                    "host": srv['test_host'],
-                    "port": srv['test_db_port'],
-                    "db": srv['test_maintenance_db'],
-                    "username": srv['test_db_username'],
-                    "role": "",
-                    "sslmode": srv['test_sslmode']}
-
-            url = self.url + str(srv_grp) + "/"
-            response = self.tester.get(url, data=json.dumps(data),
-                                       content_type='html/json')
-            self.assertTrue(response.status_code, 200)
+        for server_id in server_ids:
+            url = "{0}{1}/{2}".format(self.url, srv_grp, server_id)
+            response = self.tester.get(url, content_type='html/json')
+            self.assertEquals(response.status_code, 200)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
index 306bb03..31d3eb2 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
@@ -9,57 +9,67 @@
 
 import json
 
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 from regression.config import config_data
 
 
-class ServersUpdateTestCase(LoginTestCase):
-    """
-    This class will check server node present on the object browser's tree node
-    by response code.
-    """
-
-    priority = 6
+class ServerUpdateTestCase(BaseTestGenerator):
+    """ This class will update server's comment field. """
 
     scenarios = [
         # Fetching the default url for server node
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def runTest(self):
-        """
-        This function will edit and update the server's comment field
-        by the server id.
+    def setUp(self):
         """
+        This function perform the four tasks
+         1. Login to test client
+         2. Add the test server
+         3. Get the server
+         4. Connect to server
 
-        srv_grp = config_data['test_server_group']
-
-        for srv in config_data['test_server_credentials']:
-
-            data = {"name": srv['test_name'],
-                    "host": srv['test_host'],
-                    "port": srv['test_db_port'],
-                    "db": srv['test_maintenance_db'],
-                    "username": srv['test_db_username'],
-                    "role": "",
-                    "sslmode": srv['test_sslmode']}
-
-            url = self.url + str(srv_grp) + "/"
-
-            response = self.tester.get(url, data=json.dumps(data),
-                                       content_type='html/json')
+        :return: None
+        """
 
-            self.assertTrue(response.status_code, 200)
-            respdata = json.loads(response.data)
+        utils.login_tester_account(self.tester)
+        # Firstly, add the server
+        utils.add_server(self.tester)
+        # Get the server
+        utils.get_server(self.tester)
+        # Connect to server
+        self.server_connect, self.server_group, self.server_ids = \
+            utils.connect_server(self.tester)
+        if len(self.server_connect) == 0:
+            raise Exception("No Server(s) connected to update!!!")
 
-            for server in respdata:
+    def runTest(self):
+        """ This function will update the server's comment field. """
+
+        for server_id in self.server_ids:
+            data = {
+                "comment":
+                    config_data['test_server_update_data'][0]['test_comment'],
+                "id": server_id
+            }
+            put_response = self.tester.put(
+                self.url + str(self.server_group) + '/' +
+                str(server_id), data=json.dumps(data),
+                content_type='html/json')
+            self.assertEquals(put_response.status_code, 200)
+
+            response_data = json.loads(put_response.data.decode())
+            self.assertTrue(response_data['success'], 1)
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
 
-                url = self.url + str(srv_grp) + "/" + json.dumps(server['id'])
+        :return: None
+        """
 
-                for server in config_data['test_server_update_data']:
-                    data = {"comment": server['test_comment']}
-                    response = self.tester.put(url, data=json.dumps(data),
-                                               content_type='html/json')
-                    self.assertTrue(response.status_code, 200)
-                    respdata = json.loads(response.data)
-                    self.assertTrue(respdata['success'], 1)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/tests/__init__.py b/web/pgadmin/browser/server_groups/tests/__init__.py
index 9fabed9..7fdd5c7 100644
--- a/web/pgadmin/browser/server_groups/tests/__init__.py
+++ b/web/pgadmin/browser/server_groups/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class SGGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        print ("In SGGenerateTestCase...")
+        return
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/tests/test_sg_add.py b/web/pgadmin/browser/server_groups/tests/test_sg_add.py
deleted file mode 100644
index e70bb65..0000000
--- a/web/pgadmin/browser/server_groups/tests/test_sg_add.py
+++ /dev/null
@@ -1,36 +0,0 @@
-###########################################################################
-#
-# pgAdmin 4 - PostgreSQL Tools
-#
-# Copyright (C) 2013 - 2016, The pgAdmin Development Team
-# This software is released under the PostgreSQL Licence
-#
-###########################################################################
-
-import json
-
-from pgadmin.browser.tests.test_login import LoginTestCase
-from regression.config import config_data
-
-
-class SgNodeTestCase(LoginTestCase):
-    """
-     This class will check available server groups in pgAdmin.
-    """
-
-    priority = 1
-
-    scenarios = [
-        # Fetching the default url for server group node
-        ('Check Server Group Node', dict(url='/browser/server-group/obj/'))
-    ]
-
-    def runTest(self):
-        """This function will check available server groups."""
-
-        i = config_data['test_server_group']
-
-        response = self.tester.get(self.url + str(i), content_type='html/json')
-        self.assertTrue(response.status_code, 200)
-        respdata = json.loads(response.data)
-        self.assertTrue(respdata['id'], i)
diff --git a/web/pgadmin/browser/server_groups/tests/test_sg_get.py b/web/pgadmin/browser/server_groups/tests/test_sg_get.py
new file mode 100644
index 0000000..07bbe96
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/tests/test_sg_get.py
@@ -0,0 +1,48 @@
+###########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+###########################################################################
+
+import json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from regression.config import config_data
+
+
+class SgNodeTestCase(BaseTestGenerator):
+    """
+     This class will check available server groups in pgAdmin.
+    """
+
+    scenarios = [
+        # Fetching the default url for server group node
+        ('Check Server Group Node', dict(url='/browser/server-group/obj/'))
+    ]
+
+    def setUp(self):
+        """
+        This function login the test account before running the logout
+        test case
+        """
+
+        utils.login_tester_account(self.tester)
+
+    def runTest(self):
+        """This function will check available server groups."""
+
+        server_group_id = config_data['test_server_group']
+        response = self.tester.get(self.url + str(server_group_id),
+                                   content_type='html/json')
+        self.assertTrue(response.status_code, 200)
+        response_data = json.loads(response.data.decode('utf8'))
+        self.assertTrue(response_data['id'], server_group_id)
+
+    def tearDown(self):
+        """This function logout the test account """
+
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/__init__.py b/web/pgadmin/browser/tests/__init__.py
index 2381efd..3fab6fe 100644
--- a/web/pgadmin/browser/tests/__init__.py
+++ b/web/pgadmin/browser/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class BrowserGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        print ("In BrowserGenerateTestCase...")
+        return
\ No newline at end of file
diff --git a/web/pgadmin/browser/tests/test_change_password.py b/web/pgadmin/browser/tests/test_change_password.py
index dedb7d9..605aa0f 100644
--- a/web/pgadmin/browser/tests/test_change_password.py
+++ b/web/pgadmin/browser/tests/test_change_password.py
@@ -9,19 +9,18 @@
 
 import uuid
 
-from pgadmin.browser.tests.test_login import LoginTestCase
+from pgadmin.utils.route import BaseTestGenerator
 from regression.config import config_data
+from regression import test_utils as utils
 
 
-class ChangePasswordTestCase(LoginTestCase):
+class ChangePasswordTestCase(BaseTestGenerator):
     """
     This class validates the change password functionality
     by defining change password scenarios; where dict of
     parameters describes the scenario appended by test name.
     """
 
-    priority = 2
-
     scenarios = [
         # This testcase validates invalid confirmation password
         ('TestCase for Validating Incorrect_New_Password', dict(
@@ -48,8 +47,7 @@ class ChangePasswordTestCase(LoginTestCase):
             new_password='', new_password_confirm='',
             respdata='Password not provided')),
 
-        # This testcase validates if current entered password
-        # is incorrect
+        # This testcase validates if current entered password is incorrect
         ('TestCase for Validating Incorrect_Current_Password', dict(
             password=str(uuid.uuid4())[4:8],
             new_password=(config_data['pgAdmin4_login_credentials']
@@ -70,6 +68,7 @@ class ChangePasswordTestCase(LoginTestCase):
                 ['test_new_password']),
             respdata='You successfully changed your password.')),
         ('Reassigning_Password', dict(
+            test_case='reassigning_password',
             password=(config_data['pgAdmin4_login_credentials']
                       ['test_new_password']),
             new_password=(config_data['pgAdmin4_login_credentials']
@@ -81,14 +80,44 @@ class ChangePasswordTestCase(LoginTestCase):
 
     ]
 
+    def setUp(self):
+        """
+        This function login the test account before running the logout
+        test case
+        """
+
+        utils.login_tester_account(self.tester)
+
     def runTest(self):
         """This function will check change password functionality."""
 
+        # Check for 'test_case' exists in self For reassigning the password.
+        # Password gets change in change password test case.
+        if 'test_case' in dir(self):
+            email = \
+                config_data['pgAdmin4_login_credentials'][
+                    'test_login_username']
+            password = \
+                config_data['pgAdmin4_login_credentials'][
+                    'test_new_password']
+            response = self.tester.post('/login', data=dict(
+                email=email, password=password), follow_redirects=True)
+
         response = self.tester.get('/change', follow_redirects=True)
-        self.assertIn('pgAdmin 4 Password Change', response.data)
+        self.assertIn('pgAdmin 4 Password Change', response.data.decode())
+
         response = self.tester.post('/change', data=dict(
             password=self.password,
             new_password=self.new_password,
             new_password_confirm=self.new_password_confirm),
                                     follow_redirects=True)
-        self.assertIn(self.respdata, response.data)
+        self.assertIn(self.respdata, response.data.decode('utf-8'))
+
+    def tearDown(self):
+        """
+        This function logout the test client
+
+        :return: None
+        """
+
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/test_login.py b/web/pgadmin/browser/tests/test_login.py
index 7c2b796..8856700 100644
--- a/web/pgadmin/browser/tests/test_login.py
+++ b/web/pgadmin/browser/tests/test_login.py
@@ -8,9 +8,9 @@
 ##########################################################################
 
 import uuid
-
 from pgadmin.utils.route import BaseTestGenerator
 from regression.config import config_data
+from regression import test_utils as utils
 
 
 class LoginTestCase(BaseTestGenerator):
@@ -20,8 +20,6 @@ class LoginTestCase(BaseTestGenerator):
     describe the scenario appended by test name.
     """
 
-    priority = 0
-
     scenarios = [
         # This test case validates the invalid/incorrect password
         ('TestCase for Checking Invalid_Password', dict(
@@ -67,13 +65,28 @@ class LoginTestCase(BaseTestGenerator):
                    ['test_login_username']),
             password=(config_data['pgAdmin4_login_credentials']
                       ['test_login_password']),
-            respdata='You are currently running version'))
+            respdata='Gravatar image for %s' %
+                     config_data['pgAdmin4_login_credentials']
+                     ['test_login_username']))
     ]
 
+    def setUp(self):
+        pass
+
     def runTest(self):
         """This function checks login functionality."""
 
         response = self.tester.post('/login', data=dict(
             email=self.email, password=self.password),
                                     follow_redirects=True)
-        self.assertIn(self.respdata, response.data)
+        self.assertIn(self.respdata, response.data.decode('utf8'))
+
+    def tearDown(self):
+        """
+        This function deletes the 'parent_id.pkl' file which is created in
+        setup() function. Also this function logout the test client
+
+        :return: None
+        """
+
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/test_logout.py b/web/pgadmin/browser/tests/test_logout.py
index 8971e72..c2ccf94 100644
--- a/web/pgadmin/browser/tests/test_logout.py
+++ b/web/pgadmin/browser/tests/test_logout.py
@@ -7,38 +7,33 @@
 #
 # ##########################################################################
 
-from pgadmin.browser.tests.test_login import LoginTestCase
-from regression.config import config_data
 
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
 
-class LogoutTest(LoginTestCase):
+
+class LogoutTest(BaseTestGenerator):
     """
     This class verifies the logout functionality; provided the user is already
     logged-in. Dictionary parameters define the scenario appended by test
     name.
     """
 
-    priority = 3
-
     scenarios = [
         # This test case validate the logout page
         ('Logging Out', dict(respdata='Redirecting...'))
     ]
 
+    def setUp(self):
+        """
+        This function login the test account before running the logout
+        test case
+        """
+
+        utils.login_tester_account(self.tester)
+
     def runTest(self):
         """This function checks the logout functionality."""
 
         response = self.tester.get('/logout')
-        self.assertIn(self.respdata, response.data)
-
-    def tearDown(self):
-        """
-        Defining tear down class, which will run after each test method execute.
-        Re-logging in as further modules require login.
-        """
-
-        self.tester.post('/login', data=dict(
-            email=(config_data['pgAdmin4_login_credentials']
-                   ['test_login_username']),
-            password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password'])), follow_redirects=True)
+        self.assertIn(self.respdata, response.data.decode('utf8'))
diff --git a/web/pgadmin/browser/tests/test_reset_password.py b/web/pgadmin/browser/tests/test_reset_password.py
index 030b182..96404df 100644
--- a/web/pgadmin/browser/tests/test_reset_password.py
+++ b/web/pgadmin/browser/tests/test_reset_password.py
@@ -11,6 +11,7 @@ import uuid
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression.config import config_data
+from regression import test_utils as utils
 
 
 class ResetPasswordTestCase(BaseTestGenerator):
@@ -19,7 +20,6 @@ class ResetPasswordTestCase(BaseTestGenerator):
     scenarios; Each dict parameter describe a scenario appended by
     test name.
     """
-    priority = 1
 
     scenarios = [
         # This test case validates the empty email field
@@ -37,12 +37,29 @@ class ResetPasswordTestCase(BaseTestGenerator):
             ['test_login_username'], respdata='pgAdmin 4'))
     ]
 
+    def setUp(self):
+        """
+        This function login the test account before running the logout
+        test case
+        """
+
+        utils.login_tester_account(self.tester)
+
     def runTest(self):
         """This function checks reset password functionality."""
 
         response = self.tester.get('/reset')
-        self.assertIn('Recover pgAdmin 4 Password', response.data)
+        self.assertIn('Recover pgAdmin 4 Password', response.data.decode())
         response = self.tester.post(
             '/reset', data=dict(email=self.email),
             follow_redirects=True)
-        self.assertIn(self.respdata, response.data)
+        self.assertIn(self.respdata, response.data.decode('utf-8'))
+
+    def tearDown(self):
+        """
+        This function logout the test client
+
+        :return: None
+        """
+
+        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/utils/route.py b/web/pgadmin/utils/route.py
index fb9de69..a2cd1eb 100644
--- a/web/pgadmin/utils/route.py
+++ b/web/pgadmin/utils/route.py
@@ -52,8 +52,10 @@ class TestsGeneratorRegistry(ABCMeta):
         from werkzeug.utils import find_modules
 
         for module_name in find_modules(pkg, False, True):
-            module = import_module(module_name)
-
+            try:
+                module = import_module(module_name)
+            except ImportError:
+                pass
 
 import six
 
diff --git a/web/regression/README b/web/regression/README
index e0003e4..6a91911 100644
--- a/web/regression/README
+++ b/web/regression/README
@@ -40,29 +40,40 @@ General Information
     3. test_server_get.py
     4. test_server_update.py
 
-2) The pgAdmin4 source tree includes a file template for the server configuration
-   named ‘test_config.json.in' in the ‘pgAdmin4/web/regression’ directory. After
-   completing the pgAdmin4 configuration, you must make a working copy of the
-   template called test_config.json before modifying the file contents.
+2) The pgAdmin4 source tree includes 2 different configuration file templates.
+   One file template for the server configuration
+   named ‘test_config.json.in' and another for test configuration named
+   'test_advance_config.json.in' in the ‘pgAdmin4/web/regression’ directory.
+   After completing the pgAdmin4 configuration, you must make a working copy of
+   the templates called test_config.json and test_advance_config.json
+   before modifying the file contents.
 
-	2a) The following command copies the test_config.json.in file, creating a
-	    configuration file named test_config.json
+    2a) The following command copies the test_config.json.in file, creating a
+        configuration file named test_config.json (same way user can copy
+        test_advance_config.json.in file into test_advance_config.json)
 
-            # cp pgadmin4/web/regression/test_config.json.in \
-              pgadmin4/web/regression/test_config.json
+             # cp pgadmin4/web/regression/test_config.json.in \
+               pgadmin4/web/regression/test_config.json
 
-	2b) After creating the server configuration file, add (or modify)
-	    parameter values as per requirements. The configuration
-	    files are owned by root/user. The pgAdmin4 regression framework expects
-	    to find the files in the  directory '/<installation dir>/web/regression/'.
-	    If you move the file to another location, you must create a symbolic link
-	    that specifies the new location.
+    2b) After creating the server and test configuration file, add (or modify)
+        parameter values as per requirements. The configuration
+        files are owned by root/user. The pgAdmin4 regression framework expects
+        to find the files in the  directory '/<installation dir>/web/regression/'.
+        If you move the file to another location, you must create a symbolic
+        link that specifies the new location.
 
-	2c) Specifying Server Configuration file:
+    2c) Specifying Server Configuration file:
+
+        server details and connection properties as per their local setup. The
+        test_config file is in json format and property values are
+        case-sensitive.
+
+    2d) Specifying the Test Configuration file:
+
+        The user can add/change test data as per their need. The
+        test_advance_config file is in json format and property values are
+        case-sensitive.
 
-	    The user can use the parameters in the configuration file to specify the
-	    server details and connection properties as per their local setup. The
-	    test_config file is in json format and property values are case-sensitive.
 
 Test Data Details
 -----------------
@@ -92,5 +103,16 @@ Execution:
   and registered automatically by its module name in
   'pgadmin4/web/pgadmin/utils/test.py' file.
 
-- Execute test framework run 'regression/testsuite.py' file.
+- As the test framework is modular and dynamically locates the tests
+  package, We can now executes test framework node wise
+
+- Execute test framework for all nodes
+     run 'regression/testsuite.py --pkg all'
+
+- Execute test framework for single node at a time
+
+     Example 1) Run test framework for 'browser' node
+     run 'regression/testsuite.py --pkg browser'
 
+     Example 2) Run test framework for 'database' node
+     run 'regression/testsuite.py --pkg browser.server_groups.servers.databases'
diff --git a/web/regression/config.py b/web/regression/config.py
index bef65fb..564d1c2 100644
--- a/web/regression/config.py
+++ b/web/regression/config.py
@@ -10,7 +10,12 @@
 import json
 import os
 
-root = os.path.dirname(os.path.realpath(__file__))
+from regression.testsuite import CURRENT_PATH
 
-with open(root + '/test_config.json') as data_file:
+with open(CURRENT_PATH + '/test_config.json') as data_file:
     config_data = json.load(data_file)
+
+with open(CURRENT_PATH + '/test_advance_config.json') as data_file:
+    advance_config_data = json.load(data_file)
+
+pickle_path = os.path.join(CURRENT_PATH, 'parent_id.pkl')
diff --git a/web/regression/test_advance_config.json.in b/web/regression/test_advance_config.json.in
new file mode 100644
index 0000000..bcb867c
--- /dev/null
+++ b/web/regression/test_advance_config.json.in
@@ -0,0 +1,105 @@
+{
+  "test_add_database_data": [
+   {
+    "test_privileges_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "C",
+            "privilege": true,
+            "with_grant": true
+          },
+          {
+            "privilege_type": "T",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_conn_limit": -1,
+    "test_owner": "postgres",
+    "test_fun_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "X",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_seq_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "r",
+            "privilege": true,
+            "with_grant": false
+          },
+          {
+            "privilege_type": "w",
+            "privilege": true,
+            "with_grant": false
+          },
+          {
+            "privilege_type": "U",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_tbl_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "a",
+            "privilege": true,
+            "with_grant": true
+          },
+          {
+            "privilege_type": "r",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_type_acl": [
+      {
+        "grantee": "postgres",
+        "grantor": "postgres",
+        "privileges": [
+          {
+            "privilege_type": "U",
+            "privilege": true,
+            "with_grant": false
+          }
+        ]
+      }
+    ],
+    "test_encoding": "UTF8",
+    "test_name": "test_db_automation",
+    "test_privileges": [],
+    "test_securities": [],
+    "test_variables": []
+  }
+ ],
+
+  "test_db_update_data": [
+  {
+      "test_comment": "This is db update comment"
+  }
+ ]
+
+}
\ No newline at end of file
diff --git a/web/regression/test_utils.py b/web/regression/test_utils.py
new file mode 100644
index 0000000..14d186c
--- /dev/null
+++ b/web/regression/test_utils.py
@@ -0,0 +1,371 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import os
+import pickle
+import json
+import uuid
+
+from regression.config import config_data, advance_config_data, pickle_path
+
+SERVER_URL = '/browser/server/obj/'
+SERVER_CONNECT_URL = 'browser/server/connect/'
+DATABASE_CONNECT_URL = '/browser/database/obj/'
+
+
+def get_ids(url=pickle_path):
+    """
+    This function read the parent node's id and return it
+
+    :param url: file path from which it will red the ids
+    :type url: str
+    :return: node ids
+    :rtype: dict
+    """
+
+    output = open(url, 'rb')
+    ids = pickle.load(output)
+    output.close()
+
+    return ids
+
+
+def test_getnodes(tester=None):
+    # Connect to server and database.
+
+    if not tester:
+        return None
+
+    all_id = get_ids()
+
+    server_ids = all_id["sid"]
+    db_id = all_id["did"][0]
+    srv_grp = config_data['test_server_group']
+
+    # TODO: need to add code to handle multiple databases with servers
+    for server_id in server_ids:
+        # Connect to server
+        response = tester.post('browser/server/connect/{0}/{1}'.format(
+            srv_grp, server_id), data=dict(
+            password=config_data['test_server_credentials'][0][
+                'test_db_password']),
+            follow_redirects=True)
+
+        # Connect to database
+        con_response = tester.post(
+            'browser/database/connect/{0}/{1}/{2}'.format(
+                srv_grp, server_id, db_id), follow_redirects=True)
+        db_con = json.loads(con_response.data.decode('utf-8'))
+
+    return db_con
+
+
+def get_db_data(server_connect_data):
+    """
+    This function is used to get advance config test data for appropriate
+    server
+
+    :param server_connect_data: list of server details
+    :return data: database details
+    :rtype: dict
+    """
+
+    db_user = server_connect_data['data']['user']['name']
+
+    if db_user == "postgres":
+        # Get the advance test data of 'postgres' user
+        adv_config_data = advance_config_data[
+            'test_add_database_data'][0]
+    else:
+        # Get the advance test data of 'enterprisedb' user
+        adv_config_data = advance_config_data[
+            'test_add_database_data'][1]
+
+    data = {
+        "datacl": adv_config_data['test_privileges_acl'],
+        "datconnlimit": adv_config_data['test_conn_limit'],
+        "datowner": adv_config_data['test_owner'],
+        "deffuncacl": adv_config_data['test_fun_acl'],
+        "defseqacl": adv_config_data['test_seq_acl'],
+        "deftblacl": adv_config_data['test_tbl_acl'],
+        "deftypeacl": adv_config_data['test_type_acl'],
+        "encoding": adv_config_data['test_encoding'],
+        "name": str(uuid.uuid4())[1:8],
+        "privileges": adv_config_data['test_privileges'],
+        "securities": adv_config_data['test_securities'],
+        "variables": adv_config_data['test_variables']
+    }
+
+    return data
+
+
+def login_tester_account(tester):
+    """
+    This function login the test account using credentials mentioned in
+    config file
+
+    :param tester: test client
+    :type tester: flask test client object
+    :return: None
+    """
+
+    email = \
+        config_data['pgAdmin4_login_credentials']['test_login_username']
+    password = \
+        config_data['pgAdmin4_login_credentials']['test_login_password']
+    response = tester.post('/login', data=dict(
+        email=email, password=password), follow_redirects=True)
+
+
+def logout_tester_account(tester):
+    """
+    This function logout the test account
+
+    :param tester: test client
+    :type tester: flask test client object
+    :return: None
+    """
+
+    response = tester.get('/logout')
+
+
+def get_config_data():
+    """
+    This function get the data related to server group and database
+    like db name, host, port and username etc.
+
+    :return: server_group, db_data, pickle_id_dict
+    :rtype: server_group:dict, db_data:list, pickle_id_dict:dict
+    """
+
+    db_data = []
+
+    pickle_id_dict = {
+        "sid": [],  # server
+        "did": []  # database
+    }
+
+    server_group = config_data['test_server_group']
+
+    for srv in config_data['test_server_credentials']:
+        data = {"name": srv['test_name'],
+                "comment": "",
+                "host": srv['test_host'],
+                "port": srv['test_db_port'],
+                "db": srv['test_maintenance_db'],
+                "username": srv['test_db_username'],
+                "role": "",
+                "sslmode": srv['test_sslmode']}
+        db_data.append(data)
+    return server_group, db_data, pickle_id_dict
+
+
+def write_parent_id(response_data, pickle_id_dict):
+    """
+    This function writes the server's details to file parent_id.pkl
+
+    :param response_data: server's data
+    :type response_data: list of dictionary
+    :param pickle_id_dict: contains ids of server,database,tables etc.
+    :type pickle_id_dict: dict
+    :return: None
+    """
+
+    server_id = response_data['node']['_id']
+    if os.path.isfile(pickle_path):
+        existed_server_id = open(pickle_path, 'rb')
+        pickle_id_dict = pickle.load(existed_server_id)
+
+    pickle_id_dict["sid"].append(server_id)
+    output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, output)
+    output.close()
+
+
+def write_db_parent_id(response_data):
+    """
+    This function writes the server and database related data like server
+    name, server id , database name, database id etc.
+
+    :param response_data: server and databases details
+    :type response_data: dict
+    :return: None
+    """
+
+    db_id = response_data['node']['_id']
+    if os.path.isfile(pickle_path):
+        existing_server_id = open(pickle_path, 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+
+        pickle_id_dict["did"].append(db_id)
+
+        db_output = open(pickle_path, 'wb')
+        pickle.dump(pickle_id_dict, db_output)
+        db_output.close()
+
+
+def delete_parent_id_file():
+    """
+    This function deletes the file parent_id.pkl which contains server and
+    database details
+
+    :return: None
+    """
+
+    if os.path.isfile(pickle_path):
+        os.remove(pickle_path)
+
+
+def add_server(tester):
+    """
+    This function add the server in the existing server group
+
+    :param tester: test object
+    :type tester: flask test object
+    :return:None
+    """
+
+    server_group, db_data, pickle_id_dict = get_config_data()
+    url = "{0}{1}/".format(SERVER_URL, server_group)
+    for db_detail in db_data:
+        response = tester.post(url, data=json.dumps(db_detail),
+                               content_type='html/json')
+        response_data = json.loads(response.data.decode())
+        write_parent_id(response_data, pickle_id_dict)
+
+
+def get_server(tester):
+    """
+    This function gets the added serer details
+
+    :param tester: test client object
+    :type tester: flask test object
+    :return: response_data
+    :rtype: list
+    """
+
+    all_id = get_ids()
+    server_ids = all_id["sid"]
+    server_group = config_data['test_server_group']
+    for server_id in server_ids:
+        response = tester.get(SERVER_URL + str(server_group) + '/' +
+                              str(server_id),
+                              follow_redirects=True)
+        response_data = json.loads(response.data.decode())
+
+
+def connect_server(tester):
+    """
+    This function used to connect added server
+
+    :param tester:test client object
+    :type tester: flask test object
+    :return: server_connect, server_group, server_id
+    :rtype: server_connect:dict, server_group:dict, server_id:str
+    """
+
+    server_connect = []
+    servers = []
+
+    srv_id = get_ids()
+    server_ids = srv_id["sid"]
+    server_group = config_data['test_server_group']
+
+    # Connect to all servers
+    for server_id in server_ids:
+        response = tester.post(SERVER_CONNECT_URL + str(server_group) +
+                               '/' + server_id,
+                               data=dict(
+                                   password=config_data
+                                   ['test_server_credentials'][0]
+                                   ['test_db_password']),
+                               follow_redirects=True)
+        server_connect_detail = json.loads(response.data.decode())
+        connect_database(tester, server_connect_detail, server_id, server_group)
+        server_connect.append(server_connect_detail)
+        servers.append(server_id)
+    return server_connect, server_group, servers
+
+
+def connect_database(tester, server_connect, server_id, server_group):
+    """
+    This function is used to connect database and writes it's details to
+    file 'parent_id.pkl'
+
+    :param tester: test client object
+    :type tester: flask test client object
+    :param server_connect: server's data
+    :type server_connect: dict
+    :param server_id: server id
+    :type server_id: str
+    :param server_group: server group name
+    :type server_group: str
+    :return: None
+    """
+
+    if server_connect['data']['connected']:
+        db_data = get_db_data(server_connect)
+        db_response = tester.post(
+            DATABASE_CONNECT_URL + str(server_group) + "/" + server_id + "/",
+            data=json.dumps(db_data),
+            content_type='html/json')
+        response_data = json.loads(db_response.data.decode())
+        write_db_parent_id(response_data)
+
+
+def delete_server(tester):
+    """
+    This function used to delete the added servers
+
+    :param tester: test client object
+    :return: None
+    """
+
+    srv_grp = config_data['test_server_group']
+    all_id = get_ids()
+    server_ids = all_id["sid"]
+    url = SERVER_URL + str(srv_grp) + "/"
+
+    # Call api to delete the servers
+    for server_id in server_ids:
+        response = tester.delete(url + str(server_id))
+        assert response.status_code == 200
+        response_data = json.loads(response.data.decode())
+        assert response_data['success'] == 1
+
+
+def delete_database(tester, db_id):
+    """
+    This function used to delete the added databases
+
+    :param tester: test client object
+    :param db_id: database id to be delete
+    :type db_id: int
+    :return: None
+    """
+
+    srv_grp = config_data['test_server_group']
+    all_id = get_ids()
+    server_ids = all_id["sid"]
+
+    # TODO: Need to modify the code , to delete the databases for all
+    # TODO: servers. Currently it delete only one database.
+    #db_id = all_id["did"][0]
+
+    db_con = test_getnodes(tester)
+    if len(db_con) == 0:
+        raise Exception("No database(s) to delete!!!")
+
+    for server_id in server_ids:
+        response = tester.delete(DATABASE_CONNECT_URL + str(srv_grp) + '/' + str(
+            server_id) + '/' + str(db_id), follow_redirects=True)
+        assert response.status_code == 200
+        response_data = json.loads(response.data.decode('utf-8'))
+        assert response_data['success'] == 1
diff --git a/web/regression/testsuite.py b/web/regression/testsuite.py
index 75d437b..9c57c3e 100644
--- a/web/regression/testsuite.py
+++ b/web/regression/testsuite.py
@@ -10,16 +10,18 @@
 """ This file collect all modules/files present in tests directory and add
 them to TestSuite. """
 
+import argparse
 import os
 import sys
 import unittest
+import logging
 
 from testscenarios.scenarios import generate_scenarios
 
-# We need to include the root directory in sys.path to ensure that we can
-# find everything we need when running in the standalone runtime.
-current_path = os.path.dirname(os.path.realpath(__file__))
-root = os.path.dirname(current_path)
+CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
+
+# Set sys path to current directory so that we can import pgadmin package
+root = os.path.dirname(CURRENT_PATH)
 
 if sys.path[0] != root:
     sys.path.insert(0, root)
@@ -30,50 +32,113 @@ import config
 # Get the config database schema version. We store this in pgadmin.model
 # as it turns out that putting it in the config files isn't a great idea
 from pgadmin.model import SCHEMA_VERSION
+
 config.SETTINGS_SCHEMA_VERSION = SCHEMA_VERSION
 
-# Create the app!
+# Create the app
 app = create_app()
-
-# Disabling Cross-site request forgery(CSRF token) for testing purpose.
-# CSRF prevent session against malicious Web site, or end users who wants to
-# execute unwanted actions.
 app.config['WTF_CSRF_ENABLED'] = False
+test_client = app.test_client()
 
-from pgadmin.utils.route import TestsGeneratorRegistry
-
-# Registry will load all the testcases/modules from pgadmin path those are
-# register as BaseTestGenerator.
-TestsGeneratorRegistry.load_generators('pgadmin')
 
-# Create test client
-# werkzeug provides a test client which gives a simple interface to the
-# application. We can trigger test request to the application.
-test_client = app.test_client()
+def get_suite(arguments, test_app_client):
+    """
+     This function loads the all modules in the tests directory into testing
+     environment.
 
+    :param arguments: this is command line arguments for module name to
+    which test suite will run
+    :type arguments: str
+    :param test_app_client: test client
+    :type test_app_client: pgadmin app object
+    :return pgadmin_suite: test suite with test cases
+    :rtype: TestSuite
+    """
 
-def suite():
-    """ Defining test suite which will execute all the testcases present in
-    tests directory according to set priority."""
+    from pgadmin.utils.route import TestsGeneratorRegistry
 
+    modules = []
     pgadmin_suite = unittest.TestSuite()
 
-    modules = []
+    # Load the test modules which are in given package(i.e. in arguments.pkg)
+    if arguments.pkg == "all":
+        TestsGeneratorRegistry.load_generators('pgadmin')
+    else:
+        TestsGeneratorRegistry.load_generators('pgadmin.{}.tests'.format(
+            arguments.pkg))
 
+    # Get the each test module and add into list
     for key, klass in TestsGeneratorRegistry.registry.items():
         gen = klass
+        modules.append(gen)
 
-        modules.insert(gen.priority, gen)
-
-    for m in modules:
-        obj = m()
-        obj.setTestClient(test_client)
+    # Set the test client to each module & generate the scenarios
+    for module in modules:
+        obj = module()
+        obj.setTestClient(test_app_client)
         scenario = generate_scenarios(obj)
         pgadmin_suite.addTests(scenario)
 
     return pgadmin_suite
 
 
+def add_arguments():
+    """
+    This function parse the command line arguments(project's package name
+    e.g. browser) & add into parser
+
+    :return args: command line argument for pgadmin's package name
+    :rtype: argparse namespace
+    """
+
+    parser = argparse.ArgumentParser(description='Test suite for pgAdmin4')
+    parser.add_argument('--pkg', help='Executes the test cases of particular'
+                                      ' package')
+    arg = parser.parse_args()
+
+    return arg
+
+
+class StreamToLogger(object):
+    def __init__(self, logger, log_level=logging.INFO):
+        self.terminal = sys.stderr
+        self.logger = logger
+        self.log_level = log_level
+        self.linebuf = ''
+
+    def write(self, buf):
+        """
+        This function writes the log in the logger file as well as on console
+
+        :param buf: log message
+        :type buf: str
+        :return: None
+        """
+
+        self.terminal.write(buf)
+        for line in buf.rstrip().splitlines():
+            self.logger.log(self.log_level, line.rstrip())
+
+    def flush(self):
+        pass
+
+
 if __name__ == '__main__':
-    suite = suite()
-    tests = unittest.TextTestRunner(descriptions=True, verbosity=2).run(suite)
+    # Set basic logging configuration for log file
+    logging.basicConfig(level=logging.DEBUG,
+                        format='%(asctime)s:%(levelname)s:%(name)s:%(message)s',
+                        filename=CURRENT_PATH + "/" + "logger.log",
+                        filemode='w'
+                        )
+
+    # Create logger to write log in the logger file as well as on console
+    stderr_logger = logging.getLogger('STDERR')
+    sys.stderr = StreamToLogger(stderr_logger, logging.ERROR)
+
+    args = add_arguments()
+    suite = get_suite(args, test_client)
+    tests = unittest.TextTestRunner(stream=sys.stderr, descriptions=True,
+                                    verbosity=2).run(suite)
+
+    print("Please check output in file: logger.log placed at ",
+          CURRENT_PATH)


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-18 13:55  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Dave Page @ 2016-07-18 13:55 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Thanks - applied with some tweaks and changes, most notably:

- "--pkg all" is the default if no command line options are given.

- Output now goes in regression/regression.log

- Terminal output is limited to WARNINGS from the app server.

- The runner script is now python regression/runtests.py

On Mon, Jul 18, 2016 at 1:45 PM, Navnath Gadakh
<[email protected]> wrote:
> Hi Dave,
>
>   Please find the revised patch for unit tests of pgAdmin4 APIs.
>
> This patch includes-
>
> test_advance_config.json(for user it’s test_advance_config.json.in) for
> advance test configuration for database/server(Priyanka was working on this)
>
> test_config.json(for user it’s test_config_json.in) for basic credentials
> data for database/server
>
> From now onward we can execute test cases node wise/package wise. I have
> slightly modified the way of running the testsuite. We used the command line
> arguments(pkg) which denotes for which package testsuite going to run.
>
>
>           Run the testsuite for all packages by following command
>
>                Python regression/testsuite.py --pkg all
>
>       Here, ‘all’ means for all python
> packages(i.e.browser,server_groups,server,
>
>                             databases etc. which are same names in project
> directory structure)
>
>                This will find the ‘tests’ directory in each package &
> execute the test cases.
>
>
>
>           Run the testsuite for single package by following command
>
>       Python regression/testsuite.py --pkg browser (this execute the tests
> in ‘browser’ package only)
>
>        Python regression/testsuite.py --pkg
> browser.server_groups.servers.databases (this execute the tests in
> ‘databases’ package only)
>
>   4.  Logger file. Which include the detailed output of the testsuite.
> Testsuite also prints the test summary on the console.
>
>     5.  Previously, we set the priority to each test case. In this patch
> priority logic is removed as there is no need to set priority.
>
>     6. Resolution of AttributeError for attribute 'APP_ROOT'(Which is
> mentioned by you in a previous email)
>
>
> Note: You might get ‘AttributeError’ while running this patch on Python 3.4
> (I have raised this bug in RM(#1464)), But still you can run the testsuite.
> It will run on Python 2.7 without error.
>
>
>
> On Fri, Jul 15, 2016 at 6:23 PM, Dave Page <[email protected]>
> wrote:
>>
>> Hi
>>
>> On Mon, Jul 11, 2016 at 2:16 PM, Navnath Gadakh
>> <[email protected]> wrote:
>>>
>>> Hi Dave,
>>> PFA updated patch for modular API test cases.
>>>
>>> On Mon, Jul 11, 2016 at 5:11 PM, Dave Page <[email protected]>
>>> wrote:
>>>>
>>>>
>>>>
>>>> On Fri, Jul 8, 2016 at 2:30 PM, Navnath Gadakh
>>>> <[email protected]> wrote:
>>>>>
>>>>>
>>>>> Hi Dave,
>>>>>
>>>>> PFA patch for modular API test cases.
>>>>>
>>>>> Kindly, review the same and let me know for any modification.
>>>>
>>>>
>>>> Please re-create the patch so that it doesn't revert various changes
>>>> made to config.py etc. over the last couple of weeks.
>>>
>>>
>>>   config.py file was not updated at my end, I have updated it in the
>>> current patch.  I have also added code related to advance test data
>>> configuration which was created by Priyanka (Seprated the test data
>>> configuration files).
>>>
>>>>
>>>> What is the patch for? Is it fixing issues in Priyanka's last patch, or
>>>> something else?
>>>> This patch is for -
>>>> 1. Now we can run testsuite node/module wise(like for browser only, for
>>>> databases only)  OR for all nodes/modules
>>>> 2. I have modified the existing functionality for testsuite and all test
>>>> case classes (Made all test cases independently runnable, removed the
>>>> priority logic).
>>>
>>>
>>>
>>>     For more details please refer the file 'regression/README'.
>>
>>
>> When running all tests, I get:
>>
>> ...
>> ...
>>  <Rule '//static/<filename>' (HEAD, OPTIONS, GET) -> redirects.static>,
>>  <Rule '/backup/<filename>' (HEAD, OPTIONS, GET) -> backup.static>,
>>  <Rule '/reset/<token>' (HEAD, POST, OPTIONS, GET) ->
>> security.reset_password>,
>>  <Rule '/about/<filename>' (HEAD, OPTIONS, GET) -> about.static>])
>> Traceback (most recent call last):
>>   File "regression/testsuite.py", line 151, in <module>
>>     suite = get_suite(args, test_client)
>>   File "regression/testsuite.py", line 75, in get_suite
>>     TestsGeneratorRegistry.load_generators('pgadmin')
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/utils/route.py", line 56, in
>> load_generators
>>     module = import_module(module_name)
>>   File
>> "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py",
>> line 37, in import_module
>>     __import__(name)
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py",
>> line 14, in <module>
>>     from regression import test_utils as utils
>>   File "/Users/dpage/git/pgadmin4/web/regression/test_utils.py", line 23,
>> in <module>
>>     def get_ids(url=config.APP_ROOT + '/regression/parent_id.pkl'):
>> AttributeError: 'module' object has no attribute 'APP_ROOT'
>>
>> That's not overly surprising, as we don't have an APP_ROOT setting in the
>> config (nor should we - it should be calculated dynamically). Please fix,
>> and remember to test your patches against a clean copy of the git tree in
>> the future!
>>
>> Thanks!
>>
>> --
>> Dave Page
>> VP, Chief Architect, Tools & Installers
>> EnterpriseDB: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>
>
>
>
> --
> Thanks,
> Navnath Gadakh
> Software Engineer
> EnterpriseDB Corporation
> Mobile: +91 9975389878
>
>



-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-19 04:19  Khushboo Vashi <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Khushboo Vashi @ 2016-07-19 04:19 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: Navnath Gadakh <[email protected]>; pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Navnath,

I have just ran the automated test cases, I noticed that the login
test-case gets called (which actually post data and gets logged-in) each
time before every test case runs. I think this should not happen,  user
login should be done only once.

Thanks,
Khushboo

On Mon, Jul 18, 2016 at 7:25 PM, Dave Page <[email protected]>
wrote:

> Thanks - applied with some tweaks and changes, most notably:
>
> - "--pkg all" is the default if no command line options are given.
>
> - Output now goes in regression/regression.log
>
> - Terminal output is limited to WARNINGS from the app server.
>
> - The runner script is now python regression/runtests.py
>
> On Mon, Jul 18, 2016 at 1:45 PM, Navnath Gadakh
> <[email protected]> wrote:
> > Hi Dave,
> >
> >   Please find the revised patch for unit tests of pgAdmin4 APIs.
> >
> > This patch includes-
> >
> > test_advance_config.json(for user it’s test_advance_config.json.in) for
> > advance test configuration for database/server(Priyanka was working on
> this)
> >
> > test_config.json(for user it’s test_config_json.in) for basic
> credentials
> > data for database/server
> >
> > From now onward we can execute test cases node wise/package wise. I have
> > slightly modified the way of running the testsuite. We used the command
> line
> > arguments(pkg) which denotes for which package testsuite going to run.
> >
> >
> >           Run the testsuite for all packages by following command
> >
> >                Python regression/testsuite.py --pkg all
> >
> >       Here, ‘all’ means for all python
> > packages(i.e.browser,server_groups,server,
> >
> >                             databases etc. which are same names in
> project
> > directory structure)
> >
> >                This will find the ‘tests’ directory in each package &
> > execute the test cases.
> >
> >
> >
> >           Run the testsuite for single package by following command
> >
> >       Python regression/testsuite.py --pkg browser (this execute the
> tests
> > in ‘browser’ package only)
> >
> >        Python regression/testsuite.py --pkg
> > browser.server_groups.servers.databases (this execute the tests in
> > ‘databases’ package only)
> >
> >   4.  Logger file. Which include the detailed output of the testsuite.
> > Testsuite also prints the test summary on the console.
> >
> >     5.  Previously, we set the priority to each test case. In this patch
> > priority logic is removed as there is no need to set priority.
> >
> >     6. Resolution of AttributeError for attribute 'APP_ROOT'(Which is
> > mentioned by you in a previous email)
> >
> >
> > Note: You might get ‘AttributeError’ while running this patch on Python
> 3.4
> > (I have raised this bug in RM(#1464)), But still you can run the
> testsuite.
> > It will run on Python 2.7 without error.
> >
> >
> >
> > On Fri, Jul 15, 2016 at 6:23 PM, Dave Page <[email protected]>
> > wrote:
> >>
> >> Hi
> >>
> >> On Mon, Jul 11, 2016 at 2:16 PM, Navnath Gadakh
> >> <[email protected]> wrote:
> >>>
> >>> Hi Dave,
> >>> PFA updated patch for modular API test cases.
> >>>
> >>> On Mon, Jul 11, 2016 at 5:11 PM, Dave Page <[email protected]
> >
> >>> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On Fri, Jul 8, 2016 at 2:30 PM, Navnath Gadakh
> >>>> <[email protected]> wrote:
> >>>>>
> >>>>>
> >>>>> Hi Dave,
> >>>>>
> >>>>> PFA patch for modular API test cases.
> >>>>>
> >>>>> Kindly, review the same and let me know for any modification.
> >>>>
> >>>>
> >>>> Please re-create the patch so that it doesn't revert various changes
> >>>> made to config.py etc. over the last couple of weeks.
> >>>
> >>>
> >>>   config.py file was not updated at my end, I have updated it in the
> >>> current patch.  I have also added code related to advance test data
> >>> configuration which was created by Priyanka (Seprated the test data
> >>> configuration files).
> >>>
> >>>>
> >>>> What is the patch for? Is it fixing issues in Priyanka's last patch,
> or
> >>>> something else?
> >>>> This patch is for -
> >>>> 1. Now we can run testsuite node/module wise(like for browser only,
> for
> >>>> databases only)  OR for all nodes/modules
> >>>> 2. I have modified the existing functionality for testsuite and all
> test
> >>>> case classes (Made all test cases independently runnable, removed the
> >>>> priority logic).
> >>>
> >>>
> >>>
> >>>     For more details please refer the file 'regression/README'.
> >>
> >>
> >> When running all tests, I get:
> >>
> >> ...
> >> ...
> >>  <Rule '//static/<filename>' (HEAD, OPTIONS, GET) -> redirects.static>,
> >>  <Rule '/backup/<filename>' (HEAD, OPTIONS, GET) -> backup.static>,
> >>  <Rule '/reset/<token>' (HEAD, POST, OPTIONS, GET) ->
> >> security.reset_password>,
> >>  <Rule '/about/<filename>' (HEAD, OPTIONS, GET) -> about.static>])
> >> Traceback (most recent call last):
> >>   File "regression/testsuite.py", line 151, in <module>
> >>     suite = get_suite(args, test_client)
> >>   File "regression/testsuite.py", line 75, in get_suite
> >>     TestsGeneratorRegistry.load_generators('pgadmin')
> >>   File "/Users/dpage/git/pgadmin4/web/pgadmin/utils/route.py", line 56,
> in
> >> load_generators
> >>     module = import_module(module_name)
> >>   File
> >>
> "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py",
> >> line 37, in import_module
> >>     __import__(name)
> >>   File
> >>
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py",
> >> line 14, in <module>
> >>     from regression import test_utils as utils
> >>   File "/Users/dpage/git/pgadmin4/web/regression/test_utils.py", line
> 23,
> >> in <module>
> >>     def get_ids(url=config.APP_ROOT + '/regression/parent_id.pkl'):
> >> AttributeError: 'module' object has no attribute 'APP_ROOT'
> >>
> >> That's not overly surprising, as we don't have an APP_ROOT setting in
> the
> >> config (nor should we - it should be calculated dynamically). Please
> fix,
> >> and remember to test your patches against a clean copy of the git tree
> in
> >> the future!
> >>
> >> Thanks!
> >>
> >> --
> >> Dave Page
> >> VP, Chief Architect, Tools & Installers
> >> EnterpriseDB: http://www.enterprisedb.com
> >> The Enterprise PostgreSQL Company
> >>
> >> Blog: http://pgsnake.blogspot.com
> >> Twitter: @pgsnake
> >
> >
> >
> >
> > --
> > Thanks,
> > Navnath Gadakh
> > Software Engineer
> > EnterpriseDB Corporation
> > Mobile: +91 9975389878
> >
> >
>
>
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
>
> --
> Sent via pgadmin-hackers mailing list ([email protected])
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgadmin-hackers
>


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-22 13:22  Navnath Gadakh <[email protected]>
  parent: Khushboo Vashi <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-07-22 13:22 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,

   Please find the attached patch for pgAdmin4 unittest(Support of API
testing with different servers i.e. PG and PPAS).

*This patch includes-*

   1.

   Test framework support API testing with multiple server for this we need
   to modify test_config.json(for user it’s test_config.json.in) and
   test_advanced_config.json(for user it’s test_advanced_config.json.in).
   Server details of PG and  PPAS are included in both .in files.
   2.

   Removed the logic of logging in  the test client on each test
   scenario(As per Khushboo's comment in previous email).  We need this logic
   in test cases under ‘browser/tests/’ as for test scenarios like change
   password and  invalid login test cases as test client should be logged out
   first. So, as per this the code is slightly modified in ‘browser/tests/’.


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [text/x-patch] pgadmin_unittest_multiple_server.patch (39.8K, 3-pgadmin_unittest_multiple_server.patch)
  download | inline diff:
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
index c0e1430..85dcc6c 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
@@ -8,11 +8,9 @@
 # ##################################################################
 
 import json
-import uuid
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import advanced_config_data
 
 
 class DatabaseAddTestCase(BaseTestGenerator):
@@ -28,14 +26,11 @@ class DatabaseAddTestCase(BaseTestGenerator):
 
     def setUp(self):
         """
-        This function perform the two tasks
-         1. Login to test client
-         2. Add the test server
+        This function used to add the sever
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         # Add the server
         utils.add_server(self.tester)
 
@@ -45,8 +40,6 @@ class DatabaseAddTestCase(BaseTestGenerator):
         server_connect_response, server_group, server_ids = \
             utils.connect_server(self.tester)
 
-        # Store db id. Which is use to delete in tearDown()
-        self.db_id = ''
         for server_connect, server_id in zip(server_connect_response,
                                              server_ids):
             if server_connect['data']['connected']:
@@ -58,17 +51,15 @@ class DatabaseAddTestCase(BaseTestGenerator):
                 self.assertTrue(db_response.status_code, 200)
                 response_data = json.loads(db_response.data.decode('utf-8'))
                 utils.write_db_parent_id(response_data)
-                self.db_id = response_data['node']['_id']
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added database, added server and the
+        'parent_id.pkl' file which is created in setup()
 
         :return: None
         """
 
-        utils.delete_database(self.tester, self.db_id)
+        utils.delete_database(self.tester)
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
index 5f160f9..6830b5a 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
@@ -12,7 +12,7 @@ import json
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
 from regression.test_setup import config_data
-from regression.test_utils import get_ids, test_getnodes
+from regression.test_utils import get_ids
 
 
 class DatabaseDeleteTestCase(BaseTestGenerator):
@@ -26,14 +26,12 @@ class DatabaseDeleteTestCase(BaseTestGenerator):
     def setUp(self):
         """
         This function perform the three tasks
-         1. Login to test client
-         2. Add the test server
-         3. Connect to server
+         1. Add the test server
+         2. Connect to server
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         # Firstly, add the server
         utils.add_server(self.tester)
         # Secondly, connect to server/database
@@ -45,14 +43,15 @@ class DatabaseDeleteTestCase(BaseTestGenerator):
         srv_grp = config_data['test_server_group']
         all_id = get_ids()
         server_ids = all_id["sid"]
+        db_ids_dict = all_id["did"][0]
 
-        # TODO: Need to modify the code , to delete the databases for all
-        # TODO: servers. Currently it delete only one database.
-        db_id = all_id["did"][0]
-        db_con = test_getnodes(self.tester)
-        if len(db_con) == 0:
-            raise Exception("No database(s) to delete!!!")
         for server_id in server_ids:
+            db_id = db_ids_dict[int(server_id)]
+            db_con = utils.verify_database(self.tester, srv_grp, server_id,
+                                           db_id)
+            if len(db_con) == 0:
+                raise Exception("No database(s) to delete for server id %s"
+                                % server_id)
             response = self.tester.delete(self.url + str(srv_grp) + '/' +
                                           str(server_id) + '/' + str(db_id),
                                           follow_redirects=True)
@@ -62,12 +61,11 @@ class DatabaseDeleteTestCase(BaseTestGenerator):
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added server and the 'parent_id.pkl' file
+        which is created in setup() function.
 
         :return: None
         """
 
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
index a42e0c1..7350f72 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
@@ -10,7 +10,7 @@
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
 from regression.test_setup import config_data
-from regression.test_utils import get_ids, test_getnodes
+from regression.test_utils import get_ids
 
 
 class DatabasesGetTestCase(BaseTestGenerator):
@@ -26,14 +26,12 @@ class DatabasesGetTestCase(BaseTestGenerator):
     def setUp(self):
         """
         This function perform the three tasks
-         1. Login to test client
-         2. Add the test server
-         3. Connect to server
+         1. Add the test server
+         2. Connect to server
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         # Firstly, add the server
         utils.add_server(self.tester)
         # Secondly, connect to server/database
@@ -45,28 +43,27 @@ class DatabasesGetTestCase(BaseTestGenerator):
         all_id = get_ids()
         server_ids = all_id["sid"]
 
-        # TODO: Code is remaining to get all databases of all servers
-        self.db_id = all_id["did"][0]
+        db_ids_dict = all_id["did"][0]
         srv_grp = config_data['test_server_group']
 
         for server_id in server_ids:
-            db_con = test_getnodes(self.tester)
+            db_id = db_ids_dict[int(server_id)]
+            db_con = utils.verify_database(self.tester, srv_grp, server_id,
+                                           db_id)
             if db_con["info"] == "Database connected.":
-                response = self.tester.get(self.url + str(srv_grp) + '/' +
-                                           str(server_id) + '/' + str(
-                    self.db_id),
-                                           follow_redirects=True)
+                response = self.tester.get(
+                    self.url + str(srv_grp) + '/' + str(server_id) + '/' +
+                    str(db_id), follow_redirects=True)
                 self.assertEquals(response.status_code, 200)
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added database, added server
+        and the 'parent_id.pkl' file which is created in setup() function.
 
         :return: None
         """
 
-        utils.delete_database(self.tester, self.db_id)
+        utils.delete_database(self.tester)
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
index c5f92cc..4615d34 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
@@ -12,7 +12,7 @@ import json
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
 from regression.test_setup import config_data, advanced_config_data
-from regression.test_utils import get_ids, test_getnodes
+from regression.test_utils import get_ids
 
 
 class DatabasesUpdateTestCase(BaseTestGenerator):
@@ -28,14 +28,12 @@ class DatabasesUpdateTestCase(BaseTestGenerator):
     def setUp(self):
         """
         This function perform the three tasks
-         1. Login to test client
-         2. Add the test server
-         3. Connect to server
+         1. Add the test server
+         2. Connect to server
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         # Firstly, add the server
         utils.add_server(self.tester)
         # Secondly, connect to server/database
@@ -47,33 +45,30 @@ class DatabasesUpdateTestCase(BaseTestGenerator):
         srv_grp = config_data['test_server_group']
         all_id = get_ids()
         server_ids = all_id["sid"]
-
-        # TODO: Need to modify the code , to delete the databases for all
-        # TODO: servers. Currently it delete only one database.
-        db_id = all_id["did"][0]
-        test_getnodes(self.tester)
-
-        data = {
-            "comments": advanced_config_data["test_db_update_data"][0]
-            ["test_comment"],
-            "id": db_id
-        }
+        db_ids_dict = all_id["did"][0]
 
         for server_id in server_ids:
-            put_response = self.tester.put(self.url + str(srv_grp) + '/' +
-                                           str(server_id) + '/' + str(db_id),
-                                           data=json.dumps(data),
-                                           follow_redirects=True)
-            self.assertEquals(put_response.status_code, 200)
+            db_id = db_ids_dict[int(server_id)]
+            db_con = utils.verify_database(self.tester, srv_grp, server_id,
+                                           db_id)
+            if db_con["info"] == "Database connected.":
+                data = {
+                    "comments": advanced_config_data["test_db_update_data"][0]
+                    ["test_comment"],
+                    "id": db_id
+                }
+                put_response = self.tester.put(
+                    self.url + str(srv_grp) + '/' + str(server_id) + '/' +
+                    str(db_id), data=json.dumps(data), follow_redirects=True)
+                self.assertEquals(put_response.status_code, 200)
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added server and 'parent_id.pkl' file
+        which is created in setup() function.
 
         :return: None
         """
 
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/tests/__init__.py
index 55a3a17..4fd2066 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class ServerGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        return
\ No newline at end of file
+        return
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 0f07d21..2b1eb45 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
@@ -11,8 +11,6 @@ import json
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import config_data
-from regression.test_utils import get_ids
 
 
 class ServersAddTestCase(BaseTestGenerator):
@@ -24,12 +22,7 @@ class ServersAddTestCase(BaseTestGenerator):
     ]
 
     def setUp(self):
-        """
-        This function login the test account before running the logout
-        test case
-        """
-
-        utils.login_tester_account(self.tester)
+        pass
 
     def runTest(self):
         """ This function will add the server under default server group."""
@@ -47,12 +40,11 @@ class ServersAddTestCase(BaseTestGenerator):
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added server and the 'parent_id.pkl' file
+        which is created in setup() function.
 
         :return: None
         """
 
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
index 765a371..4fd207b 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
@@ -25,14 +25,11 @@ class ServerDeleteTestCase(BaseTestGenerator):
 
     def setUp(self):
         """
-        This function perform the two tasks
-         1. Login to test client
-         2. Add the test server
+        This function is used to add the server
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         # Firstly, add the server
         utils.add_server(self.tester)
 
@@ -58,10 +55,9 @@ class ServerDeleteTestCase(BaseTestGenerator):
     def tearDown(self):
         """
         This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        setup() function.
 
         :return: None
         """
 
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
index 6ff8e16..ea3c63f 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
@@ -26,14 +26,11 @@ class ServersGetTestCase(BaseTestGenerator):
 
     def setUp(self):
         """
-        This function perform the two tasks
-         1. Login to test client
-         2. Add the test server
+        This function is used to add the server
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         utils.add_server(self.tester)
 
     def runTest(self):
@@ -50,12 +47,11 @@ class ServersGetTestCase(BaseTestGenerator):
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added server and the 'parent_id.pkl' file
+        which is created in setup() function.
 
         :return: None
         """
 
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
index 659e674..5e810ba 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
@@ -25,15 +25,13 @@ class ServerUpdateTestCase(BaseTestGenerator):
     def setUp(self):
         """
         This function perform the four tasks
-         1. Login to test client
-         2. Add the test server
-         3. Get the server
-         4. Connect to server
+         1. Add the test server
+         2. Get the server
+         3. Connect to server
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         # Firstly, add the server
         utils.add_server(self.tester)
         # Get the server
@@ -64,12 +62,11 @@ class ServerUpdateTestCase(BaseTestGenerator):
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added server and the 'parent_id.pkl' file
+        which is created in setup() function.
 
         :return: None
         """
 
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/tests/__init__.py b/web/pgadmin/browser/server_groups/tests/__init__.py
index 7fdd5c7..94218de 100644
--- a/web/pgadmin/browser/server_groups/tests/__init__.py
+++ b/web/pgadmin/browser/server_groups/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class SGGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        return
\ No newline at end of file
+        return
diff --git a/web/pgadmin/browser/server_groups/tests/test_sg_get.py b/web/pgadmin/browser/server_groups/tests/test_sg_get.py
index adcb28a..6c164be 100644
--- a/web/pgadmin/browser/server_groups/tests/test_sg_get.py
+++ b/web/pgadmin/browser/server_groups/tests/test_sg_get.py
@@ -10,7 +10,6 @@
 import json
 
 from pgadmin.utils.route import BaseTestGenerator
-from regression import test_utils as utils
 from regression.test_setup import config_data
 
 
@@ -24,14 +23,6 @@ class SgNodeTestCase(BaseTestGenerator):
         ('Check Server Group Node', dict(url='/browser/server-group/obj/'))
     ]
 
-    def setUp(self):
-        """
-        This function login the test account before running the logout
-        test case
-        """
-
-        utils.login_tester_account(self.tester)
-
     def runTest(self):
         """This function will check available server groups."""
 
@@ -41,8 +32,3 @@ class SgNodeTestCase(BaseTestGenerator):
         self.assertTrue(response.status_code, 200)
         response_data = json.loads(response.data.decode('utf8'))
         self.assertTrue(response_data['id'], server_group_id)
-
-    def tearDown(self):
-        """This function logout the test account """
-
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/__init__.py b/web/pgadmin/browser/tests/__init__.py
index 3fab6fe..7cce332 100644
--- a/web/pgadmin/browser/tests/__init__.py
+++ b/web/pgadmin/browser/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class BrowserGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        return
\ No newline at end of file
+        return
diff --git a/web/pgadmin/browser/tests/test_change_password.py b/web/pgadmin/browser/tests/test_change_password.py
index 4b77a07..2f714a7 100644
--- a/web/pgadmin/browser/tests/test_change_password.py
+++ b/web/pgadmin/browser/tests/test_change_password.py
@@ -11,7 +11,6 @@ import uuid
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression.test_setup import config_data
-from regression import test_utils as utils
 
 
 class ChangePasswordTestCase(BaseTestGenerator):
@@ -80,14 +79,6 @@ class ChangePasswordTestCase(BaseTestGenerator):
 
     ]
 
-    def setUp(self):
-        """
-        This function login the test account before running the logout
-        test case
-        """
-
-        utils.login_tester_account(self.tester)
-
     def runTest(self):
         """This function will check change password functionality."""
 
@@ -104,7 +95,8 @@ class ChangePasswordTestCase(BaseTestGenerator):
                 email=email, password=password), follow_redirects=True)
 
         response = self.tester.get('/change', follow_redirects=True)
-        self.assertIn('pgAdmin 4 Password Change', response.data.decode())
+        self.assertIn('pgAdmin 4 Password Change', response.data.decode(
+            'utf-8'))
 
         response = self.tester.post('/change', data=dict(
             password=self.password,
@@ -112,12 +104,3 @@ class ChangePasswordTestCase(BaseTestGenerator):
             new_password_confirm=self.new_password_confirm),
                                     follow_redirects=True)
         self.assertIn(self.respdata, response.data.decode('utf-8'))
-
-    def tearDown(self):
-        """
-        This function logout the test client
-
-        :return: None
-        """
-
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/test_login.py b/web/pgadmin/browser/tests/test_login.py
index 0c8a16d..b0ea361 100644
--- a/web/pgadmin/browser/tests/test_login.py
+++ b/web/pgadmin/browser/tests/test_login.py
@@ -41,7 +41,7 @@ class LoginTestCase(BaseTestGenerator):
             respdata='Email not provided')),
 
         # This test case validates empty email and password
-        ('Empty_Creadentials', dict(
+        ('Empty_Credentials', dict(
             email='', password='',
             respdata='Email not provided')),
 
@@ -53,14 +53,14 @@ class LoginTestCase(BaseTestGenerator):
             respdata='Specified user does not exist')),
 
         # This test case validates invalid email and password
-        ('Invalid_Creadentials', dict(
+        ('Invalid_Credentials', dict(
             email=str(uuid.uuid4())[1:6] + '@xyz.com',
             password=str(uuid.uuid4())[4:8],
             respdata='Specified user does not exist')),
 
         # This test case validates the valid/correct credentials and allow user
         # to login pgAdmin 4
-        ('Valid_Creadentials', dict(
+        ('Valid_Credentials', dict(
             email=(config_data['pgAdmin4_login_credentials']
                    ['test_login_username']),
             password=(config_data['pgAdmin4_login_credentials']
@@ -71,7 +71,12 @@ class LoginTestCase(BaseTestGenerator):
     ]
 
     def setUp(self):
-        pass
+        """
+        We need to logout the test client as we are testing scenarios of
+        logging in the client like invalid password, invalid emails,
+        empty credentials etc.
+        """
+        utils.logout_tester_account(self.tester)
 
     def runTest(self):
         """This function checks login functionality."""
@@ -83,10 +88,7 @@ class LoginTestCase(BaseTestGenerator):
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
-
-        :return: None
+        We need to again login the test client as soon as test scenarios
+        finishes.
         """
-
-        utils.logout_tester_account(self.tester)
+        utils.login_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/test_logout.py b/web/pgadmin/browser/tests/test_logout.py
index c2ccf94..729f7b1 100644
--- a/web/pgadmin/browser/tests/test_logout.py
+++ b/web/pgadmin/browser/tests/test_logout.py
@@ -25,15 +25,17 @@ class LogoutTest(BaseTestGenerator):
     ]
 
     def setUp(self):
-        """
-        This function login the test account before running the logout
-        test case
-        """
-
-        utils.login_tester_account(self.tester)
+        pass
 
     def runTest(self):
         """This function checks the logout functionality."""
 
         response = self.tester.get('/logout')
         self.assertIn(self.respdata, response.data.decode('utf8'))
+
+    def tearDown(self):
+        """
+        We need to again login the test client as soon as test scenarios
+        finishes.
+        """
+        utils.login_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/test_reset_password.py b/web/pgadmin/browser/tests/test_reset_password.py
index d0a6fa7..231c40e 100644
--- a/web/pgadmin/browser/tests/test_reset_password.py
+++ b/web/pgadmin/browser/tests/test_reset_password.py
@@ -11,7 +11,6 @@ import uuid
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression.test_setup import config_data
-from regression import test_utils as utils
 
 
 class ResetPasswordTestCase(BaseTestGenerator):
@@ -37,29 +36,13 @@ class ResetPasswordTestCase(BaseTestGenerator):
             ['test_login_username'], respdata='pgAdmin 4'))
     ]
 
-    def setUp(self):
-        """
-        This function login the test account before running the logout
-        test case
-        """
-
-        utils.login_tester_account(self.tester)
-
     def runTest(self):
         """This function checks reset password functionality."""
 
         response = self.tester.get('/reset')
-        self.assertIn('Recover pgAdmin 4 Password', response.data.decode())
+        self.assertIn('Recover pgAdmin 4 Password', response.data.decode(
+            'utf-8'))
         response = self.tester.post(
             '/reset', data=dict(email=self.email),
             follow_redirects=True)
         self.assertIn(self.respdata, response.data.decode('utf-8'))
-
-    def tearDown(self):
-        """
-        This function logout the test client
-
-        :return: None
-        """
-
-        utils.logout_tester_account(self.tester)
diff --git a/web/regression/runtests.py b/web/regression/runtests.py
index 2e3520a..d11a794 100644
--- a/web/regression/runtests.py
+++ b/web/regression/runtests.py
@@ -32,6 +32,7 @@ import config
 # Get the config database schema version. We store this in pgadmin.model
 # as it turns out that putting it in the config files isn't a great idea
 from pgadmin.model import SCHEMA_VERSION
+from test_utils import login_tester_account, logout_tester_account
 
 config.SETTINGS_SCHEMA_VERSION = SCHEMA_VERSION
 
@@ -43,6 +44,8 @@ config.CONSOLE_LOG_LEVEL = WARNING
 app = create_app()
 app.config['WTF_CSRF_ENABLED'] = False
 test_client = app.test_client()
+# Login the test client
+login_tester_account(test_client)
 
 
 def get_suite(arguments, test_app_client):
@@ -65,11 +68,11 @@ def get_suite(arguments, test_app_client):
     pgadmin_suite = unittest.TestSuite()
 
     # Load the test modules which are in given package(i.e. in arguments.pkg)
-    if arguments.pkg is None or arguments.pkg == "all":
+    if arguments['pkg'] is None or arguments['pkg'] == "all":
         TestsGeneratorRegistry.load_generators('pgadmin')
     else:
         TestsGeneratorRegistry.load_generators('pgadmin.{}.tests'.format(
-            arguments.pkg))
+            arguments['pkg']))
 
     # Get the each test module and add into list
     for key, klass in TestsGeneratorRegistry.registry.items():
@@ -130,7 +133,8 @@ class StreamToLogger(object):
 if __name__ == '__main__':
     # Set basic logging configuration for log file
     logging.basicConfig(level=logging.DEBUG,
-                        format='%(asctime)s:%(levelname)s:%(name)s:%(message)s',
+                        format='%(asctime)s:%(levelname)s:%(name)s:%(message)s'
+                        ,
                         filename=CURRENT_PATH + "/" + "regression.log",
                         filemode='w'
                         )
@@ -139,9 +143,12 @@ if __name__ == '__main__':
     stderr_logger = logging.getLogger('STDERR')
     sys.stderr = StreamToLogger(stderr_logger, logging.ERROR)
 
-    args = add_arguments()
+    args = vars(add_arguments())
     suite = get_suite(args, test_client)
     tests = unittest.TextTestRunner(stream=sys.stderr, descriptions=True,
                                     verbosity=2).run(suite)
 
+    # Logout the test client
+    logout_tester_account(test_client)
+
     print("Please check output in file: %s/regression.log " % CURRENT_PATH)
diff --git a/web/regression/test_advanced_config.json.in b/web/regression/test_advanced_config.json.in
index bcb867c..c0d278b 100644
--- a/web/regression/test_advanced_config.json.in
+++ b/web/regression/test_advanced_config.json.in
@@ -93,7 +93,101 @@
     "test_privileges": [],
     "test_securities": [],
     "test_variables": []
-  }
+  },
+       {
+         "test_privileges_acl": [
+           {
+             "grantee": "enterprisedb",
+             "grantor": "enterprisedb",
+             "privileges": [
+               {
+                 "privilege_type": "C",
+                 "privilege": true,
+                 "with_grant": true
+               },
+               {
+                 "privilege_type": "T",
+                 "privilege": true,
+                 "with_grant": false
+               }
+             ]
+           }
+         ],
+         "test_conn_limit": -1,
+         "test_owner": "enterprisedb",
+         "test_fun_acl": [
+           {
+             "grantee": "enterprisedb",
+             "grantor": "enterprisedb",
+             "privileges": [
+               {
+                 "privilege_type": "X",
+                 "privilege": true,
+                 "with_grant": false
+               }
+             ]
+           }
+         ],
+         "test_seq_acl": [
+           {
+             "grantee": "enterprisedb",
+             "grantor": "enterprisedb",
+             "privileges": [
+               {
+                 "privilege_type": "r",
+                 "privilege": true,
+                 "with_grant": false
+               },
+               {
+                 "privilege_type": "w",
+                 "privilege": true,
+                 "with_grant": false
+               },
+               {
+                 "privilege_type": "U",
+                 "privilege": true,
+                 "with_grant": false
+               }
+             ]
+           }
+         ],
+         "test_tbl_acl": [
+           {
+             "grantee": "enterprisedb",
+             "grantor": "enterprisedb",
+             "privileges": [
+               {
+                 "privilege_type": "a",
+                 "privilege": true,
+                 "with_grant": true
+               },
+               {
+                 "privilege_type": "r",
+                 "privilege": true,
+                 "with_grant": false
+               }
+             ]
+           }
+         ],
+         "test_type_acl": [
+           {
+             "grantee": "enterprisedb",
+             "grantor": "enterprisedb",
+             "privileges": [
+               {
+                 "privilege_type": "U",
+                 "privilege": true,
+                 "with_grant": false
+               }
+             ]
+           }
+         ],
+         "test_encoding": "UTF8",
+         "test_name": "test_db_automation",
+         "test_privileges": [],
+         "test_securities": [],
+         "test_variables": []
+       }
  ],
 
   "test_db_update_data": [
diff --git a/web/regression/test_config.json.in b/web/regression/test_config.json.in
index d81d179..028d1e7 100644
--- a/web/regression/test_config.json.in
+++ b/web/regression/test_config.json.in
@@ -15,7 +15,17 @@
       "test_db_port": 5432,
       "test_maintenance_db": "postgres",
       "test_sslmode": "prefer"
-    }
+    },
+     {
+       "test_name": "Postgres Plus Advanced Server 9.4",
+       "test_comment": "Postgres Plus Advanced 9.4 Server (EDB Installer)",
+       "test_db_username": "enterprisedb",
+       "test_host": "localhost",
+       "test_db_password": "edb",
+       "test_db_port": 5444,
+       "test_maintenance_db": "edb",
+       "test_sslmode": "prefer"
+     }
   ],
   "test_server_update_data": [
     {
diff --git a/web/regression/test_utils.py b/web/regression/test_utils.py
index 0bcc10f..6be2bb2 100644
--- a/web/regression/test_utils.py
+++ b/web/regression/test_utils.py
@@ -12,11 +12,13 @@ import pickle
 import json
 import uuid
 
-from test_setup import config_data, advanced_config_data, pickle_path
+from test_setup import config_data, advanced_config_data, \
+    pickle_path
 
 SERVER_URL = '/browser/server/obj/'
 SERVER_CONNECT_URL = 'browser/server/connect/'
-DATABASE_CONNECT_URL = '/browser/database/obj/'
+DATABASE_URL = '/browser/database/obj/'
+DATABASE_CONNECT_URL = 'browser/database/connect/'
 
 
 def get_ids(url=pickle_path):
@@ -36,6 +38,39 @@ def get_ids(url=pickle_path):
     return ids
 
 
+def verify_database(tester, server_group, server_id, db_id):
+    """
+    This function verifies that database is exists and whether it connect
+    successfully or not
+
+    :param tester: test client
+    :type tester: flask test client object
+    :param server_group: server group id
+    :type server_group: int
+    :param server_id: server id
+    :type server_id: str
+    :param db_id: database id
+    :type db_id: str
+    :return: temp_db_con
+    :rtype: list
+    """
+
+    # Connect to server
+    response = tester.post('{0}{1}/{2}'.format(
+        SERVER_CONNECT_URL, server_group, server_id), data=dict(
+        password=config_data['test_server_credentials'][0][
+            'test_db_password']),
+        follow_redirects=True)
+
+    # Connect to database
+    con_response = tester.post('{0}{1}/{2}/{3}'.format(
+        DATABASE_CONNECT_URL, server_group, server_id, db_id),
+        follow_redirects=True)
+    temp_db_con = json.loads(con_response.data.decode('utf-8'))
+
+    return temp_db_con
+
+
 def test_getnodes(tester=None):
     # Connect to server and database.
 
@@ -45,24 +80,13 @@ def test_getnodes(tester=None):
     all_id = get_ids()
 
     server_ids = all_id["sid"]
-    db_id = all_id["did"][0]
+    db_ids_dict = all_id["did"][0]
     srv_grp = config_data['test_server_group']
 
-    # TODO: need to add code to handle multiple databases with servers
+    db_con = []
     for server_id in server_ids:
-        # Connect to server
-        response = tester.post('browser/server/connect/{0}/{1}'.format(
-            srv_grp, server_id), data=dict(
-            password=config_data['test_server_credentials'][0][
-                'test_db_password']),
-            follow_redirects=True)
-
-        # Connect to database
-        con_response = tester.post(
-            'browser/database/connect/{0}/{1}/{2}'.format(
-                srv_grp, server_id, db_id), follow_redirects=True)
-        db_con = json.loads(con_response.data.decode('utf-8'))
-
+        db_id = db_ids_dict[int(server_id)]
+        db_con.append(verify_database(tester, srv_grp, server_id, db_id))
     return db_con
 
 
@@ -76,31 +100,30 @@ def get_db_data(server_connect_data):
     :rtype: dict
     """
 
+    adv_config_data = None
+    data = None
     db_user = server_connect_data['data']['user']['name']
 
-    if db_user == "postgres":
-        # Get the advance test data of 'postgres' user
-        adv_config_data = advanced_config_data[
-            'test_add_database_data'][0]
-    else:
-        # Get the advance test data of 'enterprisedb' user
-        adv_config_data = advanced_config_data[
-            'test_add_database_data'][1]
-
-    data = {
-        "datacl": adv_config_data['test_privileges_acl'],
-        "datconnlimit": adv_config_data['test_conn_limit'],
-        "datowner": adv_config_data['test_owner'],
-        "deffuncacl": adv_config_data['test_fun_acl'],
-        "defseqacl": adv_config_data['test_seq_acl'],
-        "deftblacl": adv_config_data['test_tbl_acl'],
-        "deftypeacl": adv_config_data['test_type_acl'],
-        "encoding": adv_config_data['test_encoding'],
-        "name": str(uuid.uuid4())[1:8],
-        "privileges": adv_config_data['test_privileges'],
-        "securities": adv_config_data['test_securities'],
-        "variables": adv_config_data['test_variables']
-    }
+    # Get the config data of appropriate db user
+    for config_test_data in advanced_config_data['test_add_database_data']:
+        if db_user == config_test_data['test_owner']:
+            adv_config_data = config_test_data
+
+    if adv_config_data is not None:
+        data = {
+            "datacl": adv_config_data['test_privileges_acl'],
+            "datconnlimit": adv_config_data['test_conn_limit'],
+            "datowner": adv_config_data['test_owner'],
+            "deffuncacl": adv_config_data['test_fun_acl'],
+            "defseqacl": adv_config_data['test_seq_acl'],
+            "deftblacl": adv_config_data['test_tbl_acl'],
+            "deftypeacl": adv_config_data['test_type_acl'],
+            "encoding": adv_config_data['test_encoding'],
+            "name": str(uuid.uuid4())[1:8],
+            "privileges": adv_config_data['test_privileges'],
+            "securities": adv_config_data['test_securities'],
+            "variables": adv_config_data['test_variables']
+        }
 
     return data
 
@@ -199,13 +222,18 @@ def write_db_parent_id(response_data):
     """
 
     db_id = response_data['node']['_id']
+    server_id = response_data['node']['_pid']
     if os.path.isfile(pickle_path):
         existing_server_id = open(pickle_path, 'rb')
         tol_server_id = pickle.load(existing_server_id)
         pickle_id_dict = tol_server_id
-
-        pickle_id_dict["did"].append(db_id)
-
+        if 'did' in pickle_id_dict:
+            if pickle_id_dict['did']:
+                # Add the db_id as value in dict
+                pickle_id_dict["did"][0].update({server_id: db_id})
+            else:
+                # Create new dict with server_id and db_id
+                pickle_id_dict["did"].append({server_id: db_id})
         db_output = open(pickle_path, 'wb')
         pickle.dump(pickle_id_dict, db_output)
         db_output.close()
@@ -288,7 +316,8 @@ def connect_server(tester):
                                    ['test_db_password']),
                                follow_redirects=True)
         server_connect_detail = json.loads(response.data.decode())
-        connect_database(tester, server_connect_detail, server_id, server_group)
+        connect_database(tester, server_connect_detail, server_id,
+                         server_group)
         server_connect.append(server_connect_detail)
         servers.append(server_id)
     return server_connect, server_group, servers
@@ -313,7 +342,7 @@ def connect_database(tester, server_connect, server_id, server_group):
     if server_connect['data']['connected']:
         db_data = get_db_data(server_connect)
         db_response = tester.post(
-            DATABASE_CONNECT_URL + str(server_group) + "/" + server_id + "/",
+            DATABASE_URL + str(server_group) + "/" + server_id + "/",
             data=json.dumps(db_data),
             content_type='html/json')
         response_data = json.loads(db_response.data.decode())
@@ -341,31 +370,28 @@ def delete_server(tester):
         assert response_data['success'] == 1
 
 
-def delete_database(tester, db_id):
+def delete_database(tester):
     """
     This function used to delete the added databases
 
     :param tester: test client object
-    :param db_id: database id to be delete
-    :type db_id: int
     :return: None
     """
 
     srv_grp = config_data['test_server_group']
     all_id = get_ids()
     server_ids = all_id["sid"]
-
-    # TODO: Need to modify the code , to delete the databases for all
-    # TODO: servers. Currently it delete only one database.
-    #db_id = all_id["did"][0]
+    db_ids_dict = all_id['did'][0]
 
     db_con = test_getnodes(tester)
     if len(db_con) == 0:
         raise Exception("No database(s) to delete.")
 
     for server_id in server_ids:
-        response = tester.delete(DATABASE_CONNECT_URL + str(srv_grp) + '/' + str(
-            server_id) + '/' + str(db_id), follow_redirects=True)
+        db_id = db_ids_dict[int(server_id)]
+        response = tester.delete(DATABASE_URL + str(srv_grp) + '/' +
+                                 str(server_id) + '/' + str(db_id),
+                                 follow_redirects=True)
         assert response.status_code == 200
         response_data = json.loads(response.data.decode('utf-8'))
         assert response_data['success'] == 1


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-22 16:18  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 2 replies; 29+ messages in thread

From: Dave Page @ 2016-07-22 16:18 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi

On Fri, Jul 22, 2016 at 2:22 PM, Navnath Gadakh
<[email protected]> wrote:
> Hi Dave,
>
>    Please find the attached patch for pgAdmin4 unittest(Support of API
> testing with different servers i.e. PG and PPAS).
>
> This patch includes-
>
> Test framework support API testing with multiple server for this we need to
> modify test_config.json(for user it’s test_config.json.in) and
> test_advanced_config.json(for user it’s test_advanced_config.json.in).
> Server details of PG and  PPAS are included in both .in files.
>
> Removed the logic of logging in  the test client on each test scenario(As
> per Khushboo's comment in previous email).  We need this logic in test cases
> under ‘browser/tests/’ as for test scenarios like change password and
> invalid login test cases as test client should be logged out first. So, as
> per this the code is slightly modified in ‘browser/tests/’.

OK in principle, but it doesn't seem to work:

This function will add the server under default server group. (Default
Server Node url) ... ok

======================================================================
FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
This function checks reset password functionality. (TestCase for
Validating Empty Email)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
line 44, in runTest
    'utf-8'))
AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 3.2
Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
should be redirected automatically to target URL: <a href="/">/</a>.
If not click the link.'

======================================================================
FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
This function checks reset password functionality. (TestCase for
Validating Invalid_Email)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
line 44, in runTest
    'utf-8'))
AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 3.2
Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
should be redirected automatically to target URL: <a href="/">/</a>.
If not click the link.'

======================================================================
FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
This function checks reset password functionality. (TestCase for
Validating Valid_Email)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
line 44, in runTest
    'utf-8'))
AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 3.2
Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
should be redirected automatically to target URL: <a href="/">/</a>.
If not click the link.'

----------------------------------------------------------------------
Ran 26 tests in 30.109s

FAILED (failures=3)

It's very far from obvious what's wrong here (/reset looks just fine
to me). How can we get more useful info out of the framework?

-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-25 16:57  Navnath Gadakh <[email protected]>
  parent: Dave Page <[email protected]>
  1 sibling, 0 replies; 29+ messages in thread

From: Navnath Gadakh @ 2016-07-25 16:57 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,
             I tried to reproduce this issue at my end, but didn't work.
Also tried with clean GIT tree.
Will look more into this tomorrow.
Thanks!

On Fri, Jul 22, 2016 at 9:48 PM, Dave Page <[email protected]>
wrote:

> Hi
>
> On Fri, Jul 22, 2016 at 2:22 PM, Navnath Gadakh
> <[email protected]> wrote:
> > Hi Dave,
> >
> >    Please find the attached patch for pgAdmin4 unittest(Support of API
> > testing with different servers i.e. PG and PPAS).
> >
> > This patch includes-
> >
> > Test framework support API testing with multiple server for this we need
> to
> > modify test_config.json(for user it’s test_config.json.in) and
> > test_advanced_config.json(for user it’s test_advanced_config.json.in).
> > Server details of PG and  PPAS are included in both .in files.
> >
> > Removed the logic of logging in  the test client on each test scenario(As
> > per Khushboo's comment in previous email).  We need this logic in test
> cases
> > under ‘browser/tests/’ as for test scenarios like change password and
> > invalid login test cases as test client should be logged out first. So,
> as
> > per this the code is slightly modified in ‘browser/tests/’.
>
> OK in principle, but it doesn't seem to work:
>
> This function will add the server under default server group. (Default
> Server Node url) ... ok
>
> ======================================================================
> FAIL: runTest
> (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> This function checks reset password functionality. (TestCase for
> Validating Empty Email)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> line 44, in runTest
>     'utf-8'))
> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
> HTML PUBLIC "-//W3C//DTD HTML 3.2
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> should be redirected automatically to target URL: <a href="/">/</a>.
> If not click the link.'
>
> ======================================================================
> FAIL: runTest
> (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> This function checks reset password functionality. (TestCase for
> Validating Invalid_Email)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> line 44, in runTest
>     'utf-8'))
> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
> HTML PUBLIC "-//W3C//DTD HTML 3.2
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> should be redirected automatically to target URL: <a href="/">/</a>.
> If not click the link.'
>
> ======================================================================
> FAIL: runTest
> (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> This function checks reset password functionality. (TestCase for
> Validating Valid_Email)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> line 44, in runTest
>     'utf-8'))
> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
> HTML PUBLIC "-//W3C//DTD HTML 3.2
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> should be redirected automatically to target URL: <a href="/">/</a>.
> If not click the link.'
>
> ----------------------------------------------------------------------
> Ran 26 tests in 30.109s
>
> FAILED (failures=3)
>
> It's very far from obvious what's wrong here (/reset looks just fine
> to me). How can we get more useful info out of the framework?
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>



-- 
Thanks,
Navnath Gadakh
Software Engineer
EnterpriseDB Corporation
Mobile: +91 9975389878


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-27 12:19  Navnath Gadakh <[email protected]>
  parent: Dave Page <[email protected]>
  1 sibling, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-07-27 12:19 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,
      We have reproduced the issue you mentioned in the previous
email. We need to skip the login related test cases when SERVER_MODE =
False in the web/config_local.py.

Please find the revised patch for the same.

Thanks!


On Fri, Jul 22, 2016 at 9:48 PM, Dave Page <[email protected]> wrote:
> Hi
>
> On Fri, Jul 22, 2016 at 2:22 PM, Navnath Gadakh
> <[email protected]> wrote:
>> Hi Dave,
>>
>>    Please find the attached patch for pgAdmin4 unittest(Support of API
>> testing with different servers i.e. PG and PPAS).
>>
>> This patch includes-
>>
>> Test framework support API testing with multiple server for this we need to
>> modify test_config.json(for user it’s test_config.json.in) and
>> test_advanced_config.json(for user it’s test_advanced_config.json.in).
>> Server details of PG and  PPAS are included in both .in files.
>>
>> Removed the logic of logging in  the test client on each test scenario(As
>> per Khushboo's comment in previous email).  We need this logic in test cases
>> under ‘browser/tests/’ as for test scenarios like change password and
>> invalid login test cases as test client should be logged out first. So, as
>> per this the code is slightly modified in ‘browser/tests/’.
>
> OK in principle, but it doesn't seem to work:
>
> This function will add the server under default server group. (Default
> Server Node url) ... ok
>
> ======================================================================
> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> This function checks reset password functionality. (TestCase for
> Validating Empty Email)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> line 44, in runTest
>     'utf-8'))
> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
> HTML PUBLIC "-//W3C//DTD HTML 3.2
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> should be redirected automatically to target URL: <a href="/">/</a>.
> If not click the link.'
>
> ======================================================================
> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> This function checks reset password functionality. (TestCase for
> Validating Invalid_Email)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> line 44, in runTest
>     'utf-8'))
> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
> HTML PUBLIC "-//W3C//DTD HTML 3.2
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> should be redirected automatically to target URL: <a href="/">/</a>.
> If not click the link.'
>
> ======================================================================
> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> This function checks reset password functionality. (TestCase for
> Validating Valid_Email)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> line 44, in runTest
>     'utf-8'))
> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
> HTML PUBLIC "-//W3C//DTD HTML 3.2
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> should be redirected automatically to target URL: <a href="/">/</a>.
> If not click the link.'
>
> ----------------------------------------------------------------------
> Ran 26 tests in 30.109s
>
> FAILED (failures=3)
>
> It's very far from obvious what's wrong here (/reset looks just fine
> to me). How can we get more useful info out of the framework?
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake



-- 
Thanks,
Navnath Gadakh
Software Engineer
EnterpriseDB Corporation
Mobile: +91 9975389878


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [application/octet-stream] pgadmin_unittest_multiple_server.patch (41.0K, 2-pgadmin_unittest_multiple_server.patch)
  download | inline diff:
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
index c0e1430..85dcc6c 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
@@ -8,11 +8,9 @@
 # ##################################################################
 
 import json
-import uuid
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import advanced_config_data
 
 
 class DatabaseAddTestCase(BaseTestGenerator):
@@ -28,14 +26,11 @@ class DatabaseAddTestCase(BaseTestGenerator):
 
     def setUp(self):
         """
-        This function perform the two tasks
-         1. Login to test client
-         2. Add the test server
+        This function used to add the sever
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         # Add the server
         utils.add_server(self.tester)
 
@@ -45,8 +40,6 @@ class DatabaseAddTestCase(BaseTestGenerator):
         server_connect_response, server_group, server_ids = \
             utils.connect_server(self.tester)
 
-        # Store db id. Which is use to delete in tearDown()
-        self.db_id = ''
         for server_connect, server_id in zip(server_connect_response,
                                              server_ids):
             if server_connect['data']['connected']:
@@ -58,17 +51,15 @@ class DatabaseAddTestCase(BaseTestGenerator):
                 self.assertTrue(db_response.status_code, 200)
                 response_data = json.loads(db_response.data.decode('utf-8'))
                 utils.write_db_parent_id(response_data)
-                self.db_id = response_data['node']['_id']
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added database, added server and the
+        'parent_id.pkl' file which is created in setup()
 
         :return: None
         """
 
-        utils.delete_database(self.tester, self.db_id)
+        utils.delete_database(self.tester)
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
index 5f160f9..6830b5a 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
@@ -12,7 +12,7 @@ import json
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
 from regression.test_setup import config_data
-from regression.test_utils import get_ids, test_getnodes
+from regression.test_utils import get_ids
 
 
 class DatabaseDeleteTestCase(BaseTestGenerator):
@@ -26,14 +26,12 @@ class DatabaseDeleteTestCase(BaseTestGenerator):
     def setUp(self):
         """
         This function perform the three tasks
-         1. Login to test client
-         2. Add the test server
-         3. Connect to server
+         1. Add the test server
+         2. Connect to server
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         # Firstly, add the server
         utils.add_server(self.tester)
         # Secondly, connect to server/database
@@ -45,14 +43,15 @@ class DatabaseDeleteTestCase(BaseTestGenerator):
         srv_grp = config_data['test_server_group']
         all_id = get_ids()
         server_ids = all_id["sid"]
+        db_ids_dict = all_id["did"][0]
 
-        # TODO: Need to modify the code , to delete the databases for all
-        # TODO: servers. Currently it delete only one database.
-        db_id = all_id["did"][0]
-        db_con = test_getnodes(self.tester)
-        if len(db_con) == 0:
-            raise Exception("No database(s) to delete!!!")
         for server_id in server_ids:
+            db_id = db_ids_dict[int(server_id)]
+            db_con = utils.verify_database(self.tester, srv_grp, server_id,
+                                           db_id)
+            if len(db_con) == 0:
+                raise Exception("No database(s) to delete for server id %s"
+                                % server_id)
             response = self.tester.delete(self.url + str(srv_grp) + '/' +
                                           str(server_id) + '/' + str(db_id),
                                           follow_redirects=True)
@@ -62,12 +61,11 @@ class DatabaseDeleteTestCase(BaseTestGenerator):
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added server and the 'parent_id.pkl' file
+        which is created in setup() function.
 
         :return: None
         """
 
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
index a42e0c1..7350f72 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
@@ -10,7 +10,7 @@
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
 from regression.test_setup import config_data
-from regression.test_utils import get_ids, test_getnodes
+from regression.test_utils import get_ids
 
 
 class DatabasesGetTestCase(BaseTestGenerator):
@@ -26,14 +26,12 @@ class DatabasesGetTestCase(BaseTestGenerator):
     def setUp(self):
         """
         This function perform the three tasks
-         1. Login to test client
-         2. Add the test server
-         3. Connect to server
+         1. Add the test server
+         2. Connect to server
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         # Firstly, add the server
         utils.add_server(self.tester)
         # Secondly, connect to server/database
@@ -45,28 +43,27 @@ class DatabasesGetTestCase(BaseTestGenerator):
         all_id = get_ids()
         server_ids = all_id["sid"]
 
-        # TODO: Code is remaining to get all databases of all servers
-        self.db_id = all_id["did"][0]
+        db_ids_dict = all_id["did"][0]
         srv_grp = config_data['test_server_group']
 
         for server_id in server_ids:
-            db_con = test_getnodes(self.tester)
+            db_id = db_ids_dict[int(server_id)]
+            db_con = utils.verify_database(self.tester, srv_grp, server_id,
+                                           db_id)
             if db_con["info"] == "Database connected.":
-                response = self.tester.get(self.url + str(srv_grp) + '/' +
-                                           str(server_id) + '/' + str(
-                    self.db_id),
-                                           follow_redirects=True)
+                response = self.tester.get(
+                    self.url + str(srv_grp) + '/' + str(server_id) + '/' +
+                    str(db_id), follow_redirects=True)
                 self.assertEquals(response.status_code, 200)
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added database, added server
+        and the 'parent_id.pkl' file which is created in setup() function.
 
         :return: None
         """
 
-        utils.delete_database(self.tester, self.db_id)
+        utils.delete_database(self.tester)
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
index c5f92cc..4615d34 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
@@ -12,7 +12,7 @@ import json
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
 from regression.test_setup import config_data, advanced_config_data
-from regression.test_utils import get_ids, test_getnodes
+from regression.test_utils import get_ids
 
 
 class DatabasesUpdateTestCase(BaseTestGenerator):
@@ -28,14 +28,12 @@ class DatabasesUpdateTestCase(BaseTestGenerator):
     def setUp(self):
         """
         This function perform the three tasks
-         1. Login to test client
-         2. Add the test server
-         3. Connect to server
+         1. Add the test server
+         2. Connect to server
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         # Firstly, add the server
         utils.add_server(self.tester)
         # Secondly, connect to server/database
@@ -47,33 +45,30 @@ class DatabasesUpdateTestCase(BaseTestGenerator):
         srv_grp = config_data['test_server_group']
         all_id = get_ids()
         server_ids = all_id["sid"]
-
-        # TODO: Need to modify the code , to delete the databases for all
-        # TODO: servers. Currently it delete only one database.
-        db_id = all_id["did"][0]
-        test_getnodes(self.tester)
-
-        data = {
-            "comments": advanced_config_data["test_db_update_data"][0]
-            ["test_comment"],
-            "id": db_id
-        }
+        db_ids_dict = all_id["did"][0]
 
         for server_id in server_ids:
-            put_response = self.tester.put(self.url + str(srv_grp) + '/' +
-                                           str(server_id) + '/' + str(db_id),
-                                           data=json.dumps(data),
-                                           follow_redirects=True)
-            self.assertEquals(put_response.status_code, 200)
+            db_id = db_ids_dict[int(server_id)]
+            db_con = utils.verify_database(self.tester, srv_grp, server_id,
+                                           db_id)
+            if db_con["info"] == "Database connected.":
+                data = {
+                    "comments": advanced_config_data["test_db_update_data"][0]
+                    ["test_comment"],
+                    "id": db_id
+                }
+                put_response = self.tester.put(
+                    self.url + str(srv_grp) + '/' + str(server_id) + '/' +
+                    str(db_id), data=json.dumps(data), follow_redirects=True)
+                self.assertEquals(put_response.status_code, 200)
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added server and 'parent_id.pkl' file
+        which is created in setup() function.
 
         :return: None
         """
 
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/tests/__init__.py
index 55a3a17..4fd2066 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class ServerGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        return
\ No newline at end of file
+        return
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 0f07d21..2b1eb45 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
@@ -11,8 +11,6 @@ import json
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import config_data
-from regression.test_utils import get_ids
 
 
 class ServersAddTestCase(BaseTestGenerator):
@@ -24,12 +22,7 @@ class ServersAddTestCase(BaseTestGenerator):
     ]
 
     def setUp(self):
-        """
-        This function login the test account before running the logout
-        test case
-        """
-
-        utils.login_tester_account(self.tester)
+        pass
 
     def runTest(self):
         """ This function will add the server under default server group."""
@@ -47,12 +40,11 @@ class ServersAddTestCase(BaseTestGenerator):
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added server and the 'parent_id.pkl' file
+        which is created in setup() function.
 
         :return: None
         """
 
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
index 765a371..4fd207b 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
@@ -25,14 +25,11 @@ class ServerDeleteTestCase(BaseTestGenerator):
 
     def setUp(self):
         """
-        This function perform the two tasks
-         1. Login to test client
-         2. Add the test server
+        This function is used to add the server
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         # Firstly, add the server
         utils.add_server(self.tester)
 
@@ -58,10 +55,9 @@ class ServerDeleteTestCase(BaseTestGenerator):
     def tearDown(self):
         """
         This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        setup() function.
 
         :return: None
         """
 
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
index 6ff8e16..ea3c63f 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
@@ -26,14 +26,11 @@ class ServersGetTestCase(BaseTestGenerator):
 
     def setUp(self):
         """
-        This function perform the two tasks
-         1. Login to test client
-         2. Add the test server
+        This function is used to add the server
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         utils.add_server(self.tester)
 
     def runTest(self):
@@ -50,12 +47,11 @@ class ServersGetTestCase(BaseTestGenerator):
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added server and the 'parent_id.pkl' file
+        which is created in setup() function.
 
         :return: None
         """
 
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
index 659e674..5e810ba 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
@@ -25,15 +25,13 @@ class ServerUpdateTestCase(BaseTestGenerator):
     def setUp(self):
         """
         This function perform the four tasks
-         1. Login to test client
-         2. Add the test server
-         3. Get the server
-         4. Connect to server
+         1. Add the test server
+         2. Get the server
+         3. Connect to server
 
         :return: None
         """
 
-        utils.login_tester_account(self.tester)
         # Firstly, add the server
         utils.add_server(self.tester)
         # Get the server
@@ -64,12 +62,11 @@ class ServerUpdateTestCase(BaseTestGenerator):
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
+        This function deletes the added server and the 'parent_id.pkl' file
+        which is created in setup() function.
 
         :return: None
         """
 
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/server_groups/tests/__init__.py b/web/pgadmin/browser/server_groups/tests/__init__.py
index 7fdd5c7..94218de 100644
--- a/web/pgadmin/browser/server_groups/tests/__init__.py
+++ b/web/pgadmin/browser/server_groups/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class SGGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        return
\ No newline at end of file
+        return
diff --git a/web/pgadmin/browser/server_groups/tests/test_sg_get.py b/web/pgadmin/browser/server_groups/tests/test_sg_get.py
index adcb28a..6c164be 100644
--- a/web/pgadmin/browser/server_groups/tests/test_sg_get.py
+++ b/web/pgadmin/browser/server_groups/tests/test_sg_get.py
@@ -10,7 +10,6 @@
 import json
 
 from pgadmin.utils.route import BaseTestGenerator
-from regression import test_utils as utils
 from regression.test_setup import config_data
 
 
@@ -24,14 +23,6 @@ class SgNodeTestCase(BaseTestGenerator):
         ('Check Server Group Node', dict(url='/browser/server-group/obj/'))
     ]
 
-    def setUp(self):
-        """
-        This function login the test account before running the logout
-        test case
-        """
-
-        utils.login_tester_account(self.tester)
-
     def runTest(self):
         """This function will check available server groups."""
 
@@ -41,8 +32,3 @@ class SgNodeTestCase(BaseTestGenerator):
         self.assertTrue(response.status_code, 200)
         response_data = json.loads(response.data.decode('utf8'))
         self.assertTrue(response_data['id'], server_group_id)
-
-    def tearDown(self):
-        """This function logout the test account """
-
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/__init__.py b/web/pgadmin/browser/tests/__init__.py
index 3fab6fe..7cce332 100644
--- a/web/pgadmin/browser/tests/__init__.py
+++ b/web/pgadmin/browser/tests/__init__.py
@@ -12,4 +12,4 @@ from pgadmin.utils.route import BaseTestGenerator
 
 class BrowserGenerateTestCase(BaseTestGenerator):
     def runTest(self):
-        return
\ No newline at end of file
+        return
diff --git a/web/pgadmin/browser/tests/test_change_password.py b/web/pgadmin/browser/tests/test_change_password.py
index 4b77a07..2f714a7 100644
--- a/web/pgadmin/browser/tests/test_change_password.py
+++ b/web/pgadmin/browser/tests/test_change_password.py
@@ -11,7 +11,6 @@ import uuid
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression.test_setup import config_data
-from regression import test_utils as utils
 
 
 class ChangePasswordTestCase(BaseTestGenerator):
@@ -80,14 +79,6 @@ class ChangePasswordTestCase(BaseTestGenerator):
 
     ]
 
-    def setUp(self):
-        """
-        This function login the test account before running the logout
-        test case
-        """
-
-        utils.login_tester_account(self.tester)
-
     def runTest(self):
         """This function will check change password functionality."""
 
@@ -104,7 +95,8 @@ class ChangePasswordTestCase(BaseTestGenerator):
                 email=email, password=password), follow_redirects=True)
 
         response = self.tester.get('/change', follow_redirects=True)
-        self.assertIn('pgAdmin 4 Password Change', response.data.decode())
+        self.assertIn('pgAdmin 4 Password Change', response.data.decode(
+            'utf-8'))
 
         response = self.tester.post('/change', data=dict(
             password=self.password,
@@ -112,12 +104,3 @@ class ChangePasswordTestCase(BaseTestGenerator):
             new_password_confirm=self.new_password_confirm),
                                     follow_redirects=True)
         self.assertIn(self.respdata, response.data.decode('utf-8'))
-
-    def tearDown(self):
-        """
-        This function logout the test client
-
-        :return: None
-        """
-
-        utils.logout_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/test_login.py b/web/pgadmin/browser/tests/test_login.py
index 0c8a16d..b0ea361 100644
--- a/web/pgadmin/browser/tests/test_login.py
+++ b/web/pgadmin/browser/tests/test_login.py
@@ -41,7 +41,7 @@ class LoginTestCase(BaseTestGenerator):
             respdata='Email not provided')),
 
         # This test case validates empty email and password
-        ('Empty_Creadentials', dict(
+        ('Empty_Credentials', dict(
             email='', password='',
             respdata='Email not provided')),
 
@@ -53,14 +53,14 @@ class LoginTestCase(BaseTestGenerator):
             respdata='Specified user does not exist')),
 
         # This test case validates invalid email and password
-        ('Invalid_Creadentials', dict(
+        ('Invalid_Credentials', dict(
             email=str(uuid.uuid4())[1:6] + '@xyz.com',
             password=str(uuid.uuid4())[4:8],
             respdata='Specified user does not exist')),
 
         # This test case validates the valid/correct credentials and allow user
         # to login pgAdmin 4
-        ('Valid_Creadentials', dict(
+        ('Valid_Credentials', dict(
             email=(config_data['pgAdmin4_login_credentials']
                    ['test_login_username']),
             password=(config_data['pgAdmin4_login_credentials']
@@ -71,7 +71,12 @@ class LoginTestCase(BaseTestGenerator):
     ]
 
     def setUp(self):
-        pass
+        """
+        We need to logout the test client as we are testing scenarios of
+        logging in the client like invalid password, invalid emails,
+        empty credentials etc.
+        """
+        utils.logout_tester_account(self.tester)
 
     def runTest(self):
         """This function checks login functionality."""
@@ -83,10 +88,7 @@ class LoginTestCase(BaseTestGenerator):
 
     def tearDown(self):
         """
-        This function deletes the 'parent_id.pkl' file which is created in
-        setup() function. Also this function logout the test client
-
-        :return: None
+        We need to again login the test client as soon as test scenarios
+        finishes.
         """
-
-        utils.logout_tester_account(self.tester)
+        utils.login_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/test_logout.py b/web/pgadmin/browser/tests/test_logout.py
index c2ccf94..729f7b1 100644
--- a/web/pgadmin/browser/tests/test_logout.py
+++ b/web/pgadmin/browser/tests/test_logout.py
@@ -25,15 +25,17 @@ class LogoutTest(BaseTestGenerator):
     ]
 
     def setUp(self):
-        """
-        This function login the test account before running the logout
-        test case
-        """
-
-        utils.login_tester_account(self.tester)
+        pass
 
     def runTest(self):
         """This function checks the logout functionality."""
 
         response = self.tester.get('/logout')
         self.assertIn(self.respdata, response.data.decode('utf8'))
+
+    def tearDown(self):
+        """
+        We need to again login the test client as soon as test scenarios
+        finishes.
+        """
+        utils.login_tester_account(self.tester)
diff --git a/web/pgadmin/browser/tests/test_reset_password.py b/web/pgadmin/browser/tests/test_reset_password.py
index d0a6fa7..9420c72 100644
--- a/web/pgadmin/browser/tests/test_reset_password.py
+++ b/web/pgadmin/browser/tests/test_reset_password.py
@@ -11,7 +11,7 @@ import uuid
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression.test_setup import config_data
-from regression import test_utils as utils
+from test_utils import login_tester_account, logout_tester_account
 
 
 class ResetPasswordTestCase(BaseTestGenerator):
@@ -38,28 +38,18 @@ class ResetPasswordTestCase(BaseTestGenerator):
     ]
 
     def setUp(self):
-        """
-        This function login the test account before running the logout
-        test case
-        """
-
-        utils.login_tester_account(self.tester)
+        logout_tester_account(self.tester)
 
     def runTest(self):
         """This function checks reset password functionality."""
 
         response = self.tester.get('/reset')
-        self.assertIn('Recover pgAdmin 4 Password', response.data.decode())
+        self.assertIn('Recover pgAdmin 4 Password', response.data.decode(
+            'utf-8'))
         response = self.tester.post(
             '/reset', data=dict(email=self.email),
             follow_redirects=True)
         self.assertIn(self.respdata, response.data.decode('utf-8'))
 
     def tearDown(self):
-        """
-        This function logout the test client
-
-        :return: None
-        """
-
-        utils.logout_tester_account(self.tester)
+        login_tester_account(self.tester)
diff --git a/web/pgadmin/utils/route.py b/web/pgadmin/utils/route.py
index a2cd1eb..c7ef1f8 100644
--- a/web/pgadmin/utils/route.py
+++ b/web/pgadmin/utils/route.py
@@ -50,12 +50,24 @@ class TestsGeneratorRegistry(ABCMeta):
 
         from importlib import import_module
         from werkzeug.utils import find_modules
-
-        for module_name in find_modules(pkg, False, True):
-            try:
-                module = import_module(module_name)
-            except ImportError:
-                pass
+        import config
+
+        # Check for SERVER mode
+        if config.SERVER_MODE:
+            for module_name in find_modules(pkg, False, True):
+                try:
+                    module = import_module(module_name)
+                except ImportError:
+                    pass
+        else:
+            for module_name in find_modules(pkg, False, True):
+                try:
+                    # Exclude the test cases in browser node if SERVER_MODE
+                    # is False
+                    if "pgadmin.browser.tests" not in module_name:
+                        module = import_module(module_name)
+                except ImportError:
+                    pass
 
 import six
 
diff --git a/web/regression/runtests.py b/web/regression/runtests.py
index 2e3520a..d11a794 100644
--- a/web/regression/runtests.py
+++ b/web/regression/runtests.py
@@ -32,6 +32,7 @@ import config
 # Get the config database schema version. We store this in pgadmin.model
 # as it turns out that putting it in the config files isn't a great idea
 from pgadmin.model import SCHEMA_VERSION
+from test_utils import login_tester_account, logout_tester_account
 
 config.SETTINGS_SCHEMA_VERSION = SCHEMA_VERSION
 
@@ -43,6 +44,8 @@ config.CONSOLE_LOG_LEVEL = WARNING
 app = create_app()
 app.config['WTF_CSRF_ENABLED'] = False
 test_client = app.test_client()
+# Login the test client
+login_tester_account(test_client)
 
 
 def get_suite(arguments, test_app_client):
@@ -65,11 +68,11 @@ def get_suite(arguments, test_app_client):
     pgadmin_suite = unittest.TestSuite()
 
     # Load the test modules which are in given package(i.e. in arguments.pkg)
-    if arguments.pkg is None or arguments.pkg == "all":
+    if arguments['pkg'] is None or arguments['pkg'] == "all":
         TestsGeneratorRegistry.load_generators('pgadmin')
     else:
         TestsGeneratorRegistry.load_generators('pgadmin.{}.tests'.format(
-            arguments.pkg))
+            arguments['pkg']))
 
     # Get the each test module and add into list
     for key, klass in TestsGeneratorRegistry.registry.items():
@@ -130,7 +133,8 @@ class StreamToLogger(object):
 if __name__ == '__main__':
     # Set basic logging configuration for log file
     logging.basicConfig(level=logging.DEBUG,
-                        format='%(asctime)s:%(levelname)s:%(name)s:%(message)s',
+                        format='%(asctime)s:%(levelname)s:%(name)s:%(message)s'
+                        ,
                         filename=CURRENT_PATH + "/" + "regression.log",
                         filemode='w'
                         )
@@ -139,9 +143,12 @@ if __name__ == '__main__':
     stderr_logger = logging.getLogger('STDERR')
     sys.stderr = StreamToLogger(stderr_logger, logging.ERROR)
 
-    args = add_arguments()
+    args = vars(add_arguments())
     suite = get_suite(args, test_client)
     tests = unittest.TextTestRunner(stream=sys.stderr, descriptions=True,
                                     verbosity=2).run(suite)
 
+    # Logout the test client
+    logout_tester_account(test_client)
+
     print("Please check output in file: %s/regression.log " % CURRENT_PATH)
diff --git a/web/regression/test_advanced_config.json.in b/web/regression/test_advanced_config.json.in
index bcb867c..c0d278b 100644
--- a/web/regression/test_advanced_config.json.in
+++ b/web/regression/test_advanced_config.json.in
@@ -93,7 +93,101 @@
     "test_privileges": [],
     "test_securities": [],
     "test_variables": []
-  }
+  },
+       {
+         "test_privileges_acl": [
+           {
+             "grantee": "enterprisedb",
+             "grantor": "enterprisedb",
+             "privileges": [
+               {
+                 "privilege_type": "C",
+                 "privilege": true,
+                 "with_grant": true
+               },
+               {
+                 "privilege_type": "T",
+                 "privilege": true,
+                 "with_grant": false
+               }
+             ]
+           }
+         ],
+         "test_conn_limit": -1,
+         "test_owner": "enterprisedb",
+         "test_fun_acl": [
+           {
+             "grantee": "enterprisedb",
+             "grantor": "enterprisedb",
+             "privileges": [
+               {
+                 "privilege_type": "X",
+                 "privilege": true,
+                 "with_grant": false
+               }
+             ]
+           }
+         ],
+         "test_seq_acl": [
+           {
+             "grantee": "enterprisedb",
+             "grantor": "enterprisedb",
+             "privileges": [
+               {
+                 "privilege_type": "r",
+                 "privilege": true,
+                 "with_grant": false
+               },
+               {
+                 "privilege_type": "w",
+                 "privilege": true,
+                 "with_grant": false
+               },
+               {
+                 "privilege_type": "U",
+                 "privilege": true,
+                 "with_grant": false
+               }
+             ]
+           }
+         ],
+         "test_tbl_acl": [
+           {
+             "grantee": "enterprisedb",
+             "grantor": "enterprisedb",
+             "privileges": [
+               {
+                 "privilege_type": "a",
+                 "privilege": true,
+                 "with_grant": true
+               },
+               {
+                 "privilege_type": "r",
+                 "privilege": true,
+                 "with_grant": false
+               }
+             ]
+           }
+         ],
+         "test_type_acl": [
+           {
+             "grantee": "enterprisedb",
+             "grantor": "enterprisedb",
+             "privileges": [
+               {
+                 "privilege_type": "U",
+                 "privilege": true,
+                 "with_grant": false
+               }
+             ]
+           }
+         ],
+         "test_encoding": "UTF8",
+         "test_name": "test_db_automation",
+         "test_privileges": [],
+         "test_securities": [],
+         "test_variables": []
+       }
  ],
 
   "test_db_update_data": [
diff --git a/web/regression/test_config.json.in b/web/regression/test_config.json.in
index d81d179..028d1e7 100644
--- a/web/regression/test_config.json.in
+++ b/web/regression/test_config.json.in
@@ -15,7 +15,17 @@
       "test_db_port": 5432,
       "test_maintenance_db": "postgres",
       "test_sslmode": "prefer"
-    }
+    },
+     {
+       "test_name": "Postgres Plus Advanced Server 9.4",
+       "test_comment": "Postgres Plus Advanced 9.4 Server (EDB Installer)",
+       "test_db_username": "enterprisedb",
+       "test_host": "localhost",
+       "test_db_password": "edb",
+       "test_db_port": 5444,
+       "test_maintenance_db": "edb",
+       "test_sslmode": "prefer"
+     }
   ],
   "test_server_update_data": [
     {
diff --git a/web/regression/test_utils.py b/web/regression/test_utils.py
index 0bcc10f..6be2bb2 100644
--- a/web/regression/test_utils.py
+++ b/web/regression/test_utils.py
@@ -12,11 +12,13 @@ import pickle
 import json
 import uuid
 
-from test_setup import config_data, advanced_config_data, pickle_path
+from test_setup import config_data, advanced_config_data, \
+    pickle_path
 
 SERVER_URL = '/browser/server/obj/'
 SERVER_CONNECT_URL = 'browser/server/connect/'
-DATABASE_CONNECT_URL = '/browser/database/obj/'
+DATABASE_URL = '/browser/database/obj/'
+DATABASE_CONNECT_URL = 'browser/database/connect/'
 
 
 def get_ids(url=pickle_path):
@@ -36,6 +38,39 @@ def get_ids(url=pickle_path):
     return ids
 
 
+def verify_database(tester, server_group, server_id, db_id):
+    """
+    This function verifies that database is exists and whether it connect
+    successfully or not
+
+    :param tester: test client
+    :type tester: flask test client object
+    :param server_group: server group id
+    :type server_group: int
+    :param server_id: server id
+    :type server_id: str
+    :param db_id: database id
+    :type db_id: str
+    :return: temp_db_con
+    :rtype: list
+    """
+
+    # Connect to server
+    response = tester.post('{0}{1}/{2}'.format(
+        SERVER_CONNECT_URL, server_group, server_id), data=dict(
+        password=config_data['test_server_credentials'][0][
+            'test_db_password']),
+        follow_redirects=True)
+
+    # Connect to database
+    con_response = tester.post('{0}{1}/{2}/{3}'.format(
+        DATABASE_CONNECT_URL, server_group, server_id, db_id),
+        follow_redirects=True)
+    temp_db_con = json.loads(con_response.data.decode('utf-8'))
+
+    return temp_db_con
+
+
 def test_getnodes(tester=None):
     # Connect to server and database.
 
@@ -45,24 +80,13 @@ def test_getnodes(tester=None):
     all_id = get_ids()
 
     server_ids = all_id["sid"]
-    db_id = all_id["did"][0]
+    db_ids_dict = all_id["did"][0]
     srv_grp = config_data['test_server_group']
 
-    # TODO: need to add code to handle multiple databases with servers
+    db_con = []
     for server_id in server_ids:
-        # Connect to server
-        response = tester.post('browser/server/connect/{0}/{1}'.format(
-            srv_grp, server_id), data=dict(
-            password=config_data['test_server_credentials'][0][
-                'test_db_password']),
-            follow_redirects=True)
-
-        # Connect to database
-        con_response = tester.post(
-            'browser/database/connect/{0}/{1}/{2}'.format(
-                srv_grp, server_id, db_id), follow_redirects=True)
-        db_con = json.loads(con_response.data.decode('utf-8'))
-
+        db_id = db_ids_dict[int(server_id)]
+        db_con.append(verify_database(tester, srv_grp, server_id, db_id))
     return db_con
 
 
@@ -76,31 +100,30 @@ def get_db_data(server_connect_data):
     :rtype: dict
     """
 
+    adv_config_data = None
+    data = None
     db_user = server_connect_data['data']['user']['name']
 
-    if db_user == "postgres":
-        # Get the advance test data of 'postgres' user
-        adv_config_data = advanced_config_data[
-            'test_add_database_data'][0]
-    else:
-        # Get the advance test data of 'enterprisedb' user
-        adv_config_data = advanced_config_data[
-            'test_add_database_data'][1]
-
-    data = {
-        "datacl": adv_config_data['test_privileges_acl'],
-        "datconnlimit": adv_config_data['test_conn_limit'],
-        "datowner": adv_config_data['test_owner'],
-        "deffuncacl": adv_config_data['test_fun_acl'],
-        "defseqacl": adv_config_data['test_seq_acl'],
-        "deftblacl": adv_config_data['test_tbl_acl'],
-        "deftypeacl": adv_config_data['test_type_acl'],
-        "encoding": adv_config_data['test_encoding'],
-        "name": str(uuid.uuid4())[1:8],
-        "privileges": adv_config_data['test_privileges'],
-        "securities": adv_config_data['test_securities'],
-        "variables": adv_config_data['test_variables']
-    }
+    # Get the config data of appropriate db user
+    for config_test_data in advanced_config_data['test_add_database_data']:
+        if db_user == config_test_data['test_owner']:
+            adv_config_data = config_test_data
+
+    if adv_config_data is not None:
+        data = {
+            "datacl": adv_config_data['test_privileges_acl'],
+            "datconnlimit": adv_config_data['test_conn_limit'],
+            "datowner": adv_config_data['test_owner'],
+            "deffuncacl": adv_config_data['test_fun_acl'],
+            "defseqacl": adv_config_data['test_seq_acl'],
+            "deftblacl": adv_config_data['test_tbl_acl'],
+            "deftypeacl": adv_config_data['test_type_acl'],
+            "encoding": adv_config_data['test_encoding'],
+            "name": str(uuid.uuid4())[1:8],
+            "privileges": adv_config_data['test_privileges'],
+            "securities": adv_config_data['test_securities'],
+            "variables": adv_config_data['test_variables']
+        }
 
     return data
 
@@ -199,13 +222,18 @@ def write_db_parent_id(response_data):
     """
 
     db_id = response_data['node']['_id']
+    server_id = response_data['node']['_pid']
     if os.path.isfile(pickle_path):
         existing_server_id = open(pickle_path, 'rb')
         tol_server_id = pickle.load(existing_server_id)
         pickle_id_dict = tol_server_id
-
-        pickle_id_dict["did"].append(db_id)
-
+        if 'did' in pickle_id_dict:
+            if pickle_id_dict['did']:
+                # Add the db_id as value in dict
+                pickle_id_dict["did"][0].update({server_id: db_id})
+            else:
+                # Create new dict with server_id and db_id
+                pickle_id_dict["did"].append({server_id: db_id})
         db_output = open(pickle_path, 'wb')
         pickle.dump(pickle_id_dict, db_output)
         db_output.close()
@@ -288,7 +316,8 @@ def connect_server(tester):
                                    ['test_db_password']),
                                follow_redirects=True)
         server_connect_detail = json.loads(response.data.decode())
-        connect_database(tester, server_connect_detail, server_id, server_group)
+        connect_database(tester, server_connect_detail, server_id,
+                         server_group)
         server_connect.append(server_connect_detail)
         servers.append(server_id)
     return server_connect, server_group, servers
@@ -313,7 +342,7 @@ def connect_database(tester, server_connect, server_id, server_group):
     if server_connect['data']['connected']:
         db_data = get_db_data(server_connect)
         db_response = tester.post(
-            DATABASE_CONNECT_URL + str(server_group) + "/" + server_id + "/",
+            DATABASE_URL + str(server_group) + "/" + server_id + "/",
             data=json.dumps(db_data),
             content_type='html/json')
         response_data = json.loads(db_response.data.decode())
@@ -341,31 +370,28 @@ def delete_server(tester):
         assert response_data['success'] == 1
 
 
-def delete_database(tester, db_id):
+def delete_database(tester):
     """
     This function used to delete the added databases
 
     :param tester: test client object
-    :param db_id: database id to be delete
-    :type db_id: int
     :return: None
     """
 
     srv_grp = config_data['test_server_group']
     all_id = get_ids()
     server_ids = all_id["sid"]
-
-    # TODO: Need to modify the code , to delete the databases for all
-    # TODO: servers. Currently it delete only one database.
-    #db_id = all_id["did"][0]
+    db_ids_dict = all_id['did'][0]
 
     db_con = test_getnodes(tester)
     if len(db_con) == 0:
         raise Exception("No database(s) to delete.")
 
     for server_id in server_ids:
-        response = tester.delete(DATABASE_CONNECT_URL + str(srv_grp) + '/' + str(
-            server_id) + '/' + str(db_id), follow_redirects=True)
+        db_id = db_ids_dict[int(server_id)]
+        response = tester.delete(DATABASE_URL + str(srv_grp) + '/' +
+                                 str(server_id) + '/' + str(db_id),
+                                 follow_redirects=True)
         assert response.status_code == 200
         response_data = json.loads(response.data.decode('utf-8'))
         assert response_data['success'] == 1


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-27 14:42  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 2 replies; 29+ messages in thread

From: Dave Page @ 2016-07-27 14:42 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Ahh, that explains it. Nice catch! It's working in both server and
desktop modes now :-).

I've committed the patch, but can you please look at the following issues:

1) When testing SMTP, the encoded password used to connect to the
server is displayed in both the logs and stdout (the "send: 'AUTH
PLAIN ....'" lines). Can you catch that, and replace it with *'s
please? Sooner or later someone will reveal a password otherwise.

2) Is the test count in the summary correct when you have multiple
servers? I think it might be resetting between servers.

3) Please ensure that test databases that are created are also dropped
again. I'm getting tired of deleting them manually!

Thanks, Dave.

On Wed, Jul 27, 2016 at 1:19 PM, Navnath Gadakh
<[email protected]> wrote:
> Hi Dave,
>       We have reproduced the issue you mentioned in the previous
> email. We need to skip the login related test cases when SERVER_MODE =
> False in the web/config_local.py.
>
> Please find the revised patch for the same.
>
> Thanks!
>
>
> On Fri, Jul 22, 2016 at 9:48 PM, Dave Page <[email protected]> wrote:
>> Hi
>>
>> On Fri, Jul 22, 2016 at 2:22 PM, Navnath Gadakh
>> <[email protected]> wrote:
>>> Hi Dave,
>>>
>>>    Please find the attached patch for pgAdmin4 unittest(Support of API
>>> testing with different servers i.e. PG and PPAS).
>>>
>>> This patch includes-
>>>
>>> Test framework support API testing with multiple server for this we need to
>>> modify test_config.json(for user it’s test_config.json.in) and
>>> test_advanced_config.json(for user it’s test_advanced_config.json.in).
>>> Server details of PG and  PPAS are included in both .in files.
>>>
>>> Removed the logic of logging in  the test client on each test scenario(As
>>> per Khushboo's comment in previous email).  We need this logic in test cases
>>> under ‘browser/tests/’ as for test scenarios like change password and
>>> invalid login test cases as test client should be logged out first. So, as
>>> per this the code is slightly modified in ‘browser/tests/’.
>>
>> OK in principle, but it doesn't seem to work:
>>
>> This function will add the server under default server group. (Default
>> Server Node url) ... ok
>>
>> ======================================================================
>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>> This function checks reset password functionality. (TestCase for
>> Validating Empty Email)
>> ----------------------------------------------------------------------
>> Traceback (most recent call last):
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>> line 44, in runTest
>>     'utf-8'))
>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>> should be redirected automatically to target URL: <a href="/">/</a>.
>> If not click the link.'
>>
>> ======================================================================
>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>> This function checks reset password functionality. (TestCase for
>> Validating Invalid_Email)
>> ----------------------------------------------------------------------
>> Traceback (most recent call last):
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>> line 44, in runTest
>>     'utf-8'))
>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>> should be redirected automatically to target URL: <a href="/">/</a>.
>> If not click the link.'
>>
>> ======================================================================
>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>> This function checks reset password functionality. (TestCase for
>> Validating Valid_Email)
>> ----------------------------------------------------------------------
>> Traceback (most recent call last):
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>> line 44, in runTest
>>     'utf-8'))
>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>> should be redirected automatically to target URL: <a href="/">/</a>.
>> If not click the link.'
>>
>> ----------------------------------------------------------------------
>> Ran 26 tests in 30.109s
>>
>> FAILED (failures=3)
>>
>> It's very far from obvious what's wrong here (/reset looks just fine
>> to me). How can we get more useful info out of the framework?
>>
>> --
>> Dave Page
>> VP, Chief Architect, Tools & Installers
>> EnterpriseDB: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>
>
>
> --
> Thanks,
> Navnath Gadakh
> Software Engineer
> EnterpriseDB Corporation
> Mobile: +91 9975389878



-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-27 15:27  Priyanka Shendge <[email protected]>
  parent: Dave Page <[email protected]>
  1 sibling, 0 replies; 29+ messages in thread

From: Priyanka Shendge @ 2016-07-27 15:27 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: Navnath Gadakh <[email protected]>; pgadmin-hackers; Kanchan Mohitey <[email protected]>; Khushboo Vashi <[email protected]>

On 27 July 2016 at 20:12, Dave Page <[email protected]> wrote:

> Ahh, that explains it. Nice catch! It's working in both server and
> desktop modes now :-).
>

Great. Thanks to Khushboo for helping Navnath in this task.

Thank you.


> On Wed, Jul 27, 2016 at 1:19 PM, Navnath Gadakh
> <[email protected]> wrote:
> > Hi Dave,
> >       We have reproduced the issue you mentioned in the previous
> > email. We need to skip the login related test cases when SERVER_MODE =
> > False in the web/config_local.py.
> >
> > Please find the revised patch for the same.
> >
> > Thanks!
> >
> >
> > On Fri, Jul 22, 2016 at 9:48 PM, Dave Page <[email protected]>
> wrote:
> >> Hi
> >>
> >> On Fri, Jul 22, 2016 at 2:22 PM, Navnath Gadakh
> >> <[email protected]> wrote:
> >>> Hi Dave,
> >>>
> >>>    Please find the attached patch for pgAdmin4 unittest(Support of API
> >>> testing with different servers i.e. PG and PPAS).
> >>>
> >>> This patch includes-
> >>>
> >>> Test framework support API testing with multiple server for this we
> need to
> >>> modify test_config.json(for user it’s test_config.json.in) and
> >>> test_advanced_config.json(for user it’s test_advanced_config.json.in).
> >>> Server details of PG and  PPAS are included in both .in files.
> >>>
> >>> Removed the logic of logging in  the test client on each test
> scenario(As
> >>> per Khushboo's comment in previous email).  We need this logic in test
> cases
> >>> under ‘browser/tests/’ as for test scenarios like change password and
> >>> invalid login test cases as test client should be logged out first.
> So, as
> >>> per this the code is slightly modified in ‘browser/tests/’.
> >>
> >> OK in principle, but it doesn't seem to work:
> >>
> >> This function will add the server under default server group. (Default
> >> Server Node url) ... ok
> >>
> >> ======================================================================
> >> FAIL: runTest
> (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> >> This function checks reset password functionality. (TestCase for
> >> Validating Empty Email)
> >> ----------------------------------------------------------------------
> >> Traceback (most recent call last):
> >>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> >> line 44, in runTest
> >>     'utf-8'))
> >> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
> >> HTML PUBLIC "-//W3C//DTD HTML 3.2
> >>
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> >> should be redirected automatically to target URL: <a href="/">/</a>.
> >> If not click the link.'
> >>
> >> ======================================================================
> >> FAIL: runTest
> (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> >> This function checks reset password functionality. (TestCase for
> >> Validating Invalid_Email)
> >> ----------------------------------------------------------------------
> >> Traceback (most recent call last):
> >>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> >> line 44, in runTest
> >>     'utf-8'))
> >> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
> >> HTML PUBLIC "-//W3C//DTD HTML 3.2
> >>
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> >> should be redirected automatically to target URL: <a href="/">/</a>.
> >> If not click the link.'
> >>
> >> ======================================================================
> >> FAIL: runTest
> (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> >> This function checks reset password functionality. (TestCase for
> >> Validating Valid_Email)
> >> ----------------------------------------------------------------------
> >> Traceback (most recent call last):
> >>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> >> line 44, in runTest
> >>     'utf-8'))
> >> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
> >> HTML PUBLIC "-//W3C//DTD HTML 3.2
> >>
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> >> should be redirected automatically to target URL: <a href="/">/</a>.
> >> If not click the link.'
> >>
> >> ----------------------------------------------------------------------
> >> Ran 26 tests in 30.109s
> >>
> >> FAILED (failures=3)
> >>
> >> It's very far from obvious what's wrong here (/reset looks just fine
> >> to me). How can we get more useful info out of the framework?
> >>
> >> --
> >> Dave Page
> >> VP, Chief Architect, Tools & Installers
> >> EnterpriseDB: http://www.enterprisedb.com
> >> The Enterprise PostgreSQL Company
> >>
> >> Blog: http://pgsnake.blogspot.com
> >> Twitter: @pgsnake
> >
> >
> >
> > --
> > Thanks,
> > Navnath Gadakh
> > Software Engineer
> > EnterpriseDB Corporation
> > Mobile: +91 9975389878
>
>
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
>
> --
> Sent via pgadmin-hackers mailing list ([email protected])
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgadmin-hackers
>



-- 
Best,
Priyanka

EnterpriseDB Corporation
The Enterprise PostgreSQL Company


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-07-28 07:12  Navnath Gadakh <[email protected]>
  parent: Dave Page <[email protected]>
  1 sibling, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-07-28 07:12 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Thanks Dave!

On Wed, Jul 27, 2016 at 8:12 PM, Dave Page <[email protected]> wrote:
> Ahh, that explains it. Nice catch! It's working in both server and
> desktop modes now :-).
>
> I've committed the patch, but can you please look at the following issues:
>
> 1) When testing SMTP, the encoded password used to connect to the
> server is displayed in both the logs and stdout (the "send: 'AUTH
> PLAIN ....'" lines). Can you catch that, and replace it with *'s
> please? Sooner or later someone will reveal a password otherwise.
  Sure. I will implement in the next patch.
>
> 2) Is the test count in the summary correct when you have multiple
> servers? I think it might be resetting between servers.
     In the current code runTest() function calls only one time for
single/multiple server/s that's why it's showing same count for both
(single & multiple).
   Question: What exactly we are looking for, only count? Or we need
any more logs like for adding database, it should display in which
server (PG/PPAS) its adding database if this is the case we need a
feasibility check.

>
> 3) Please ensure that test databases that are created are also dropped
> again. I'm getting tired of deleting them manually!
    I already added delete databases in tearDown () function, But
yeah, I found two test cases where this code missed. I will add this
in the next patch.

>
> Thanks, Dave.
>
> On Wed, Jul 27, 2016 at 1:19 PM, Navnath Gadakh
> <[email protected]> wrote:
>> Hi Dave,
>>       We have reproduced the issue you mentioned in the previous
>> email. We need to skip the login related test cases when SERVER_MODE =
>> False in the web/config_local.py.
>>
>> Please find the revised patch for the same.
>>
>> Thanks!
>>
>>
>> On Fri, Jul 22, 2016 at 9:48 PM, Dave Page <[email protected]> wrote:
>>> Hi
>>>
>>> On Fri, Jul 22, 2016 at 2:22 PM, Navnath Gadakh
>>> <[email protected]> wrote:
>>>> Hi Dave,
>>>>
>>>>    Please find the attached patch for pgAdmin4 unittest(Support of API
>>>> testing with different servers i.e. PG and PPAS).
>>>>
>>>> This patch includes-
>>>>
>>>> Test framework support API testing with multiple server for this we need to
>>>> modify test_config.json(for user it’s test_config.json.in) and
>>>> test_advanced_config.json(for user it’s test_advanced_config.json.in).
>>>> Server details of PG and  PPAS are included in both .in files.
>>>>
>>>> Removed the logic of logging in  the test client on each test scenario(As
>>>> per Khushboo's comment in previous email).  We need this logic in test cases
>>>> under ‘browser/tests/’ as for test scenarios like change password and
>>>> invalid login test cases as test client should be logged out first. So, as
>>>> per this the code is slightly modified in ‘browser/tests/’.
>>>
>>> OK in principle, but it doesn't seem to work:
>>>
>>> This function will add the server under default server group. (Default
>>> Server Node url) ... ok
>>>
>>> ======================================================================
>>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>>> This function checks reset password functionality. (TestCase for
>>> Validating Empty Email)
>>> ----------------------------------------------------------------------
>>> Traceback (most recent call last):
>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>>> line 44, in runTest
>>>     'utf-8'))
>>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>>> should be redirected automatically to target URL: <a href="/">/</a>.
>>> If not click the link.'
>>>
>>> ======================================================================
>>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>>> This function checks reset password functionality. (TestCase for
>>> Validating Invalid_Email)
>>> ----------------------------------------------------------------------
>>> Traceback (most recent call last):
>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>>> line 44, in runTest
>>>     'utf-8'))
>>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>>> should be redirected automatically to target URL: <a href="/">/</a>.
>>> If not click the link.'
>>>
>>> ======================================================================
>>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>>> This function checks reset password functionality. (TestCase for
>>> Validating Valid_Email)
>>> ----------------------------------------------------------------------
>>> Traceback (most recent call last):
>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>>> line 44, in runTest
>>>     'utf-8'))
>>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>>> should be redirected automatically to target URL: <a href="/">/</a>.
>>> If not click the link.'
>>>
>>> ----------------------------------------------------------------------
>>> Ran 26 tests in 30.109s
>>>
>>> FAILED (failures=3)
>>>
>>> It's very far from obvious what's wrong here (/reset looks just fine
>>> to me). How can we get more useful info out of the framework?
>>>
>>> --
>>> Dave Page
>>> VP, Chief Architect, Tools & Installers
>>> EnterpriseDB: http://www.enterprisedb.com
>>> The Enterprise PostgreSQL Company
>>>
>>> Blog: http://pgsnake.blogspot.com
>>> Twitter: @pgsnake
>>
>>
>>
>> --
>> Thanks,
>> Navnath Gadakh
>> Software Engineer
>> EnterpriseDB Corporation
>> Mobile: +91 9975389878
>
>
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake



-- 
Thanks,
Navnath Gadakh
Software Engineer
EnterpriseDB Corporation
Mobile: +91 9975389878


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-01 09:47  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Dave Page @ 2016-08-01 09:47 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

On Thu, Jul 28, 2016 at 8:12 AM, Navnath Gadakh
<[email protected]> wrote:
> Thanks Dave!
>
> On Wed, Jul 27, 2016 at 8:12 PM, Dave Page <[email protected]> wrote:
>> Ahh, that explains it. Nice catch! It's working in both server and
>> desktop modes now :-).
>>
>> I've committed the patch, but can you please look at the following issues:
>>
>> 1) When testing SMTP, the encoded password used to connect to the
>> server is displayed in both the logs and stdout (the "send: 'AUTH
>> PLAIN ....'" lines). Can you catch that, and replace it with *'s
>> please? Sooner or later someone will reveal a password otherwise.
>   Sure. I will implement in the next patch.
>>
>> 2) Is the test count in the summary correct when you have multiple
>> servers? I think it might be resetting between servers.
>      In the current code runTest() function calls only one time for
> single/multiple server/s that's why it's showing same count for both
> (single & multiple).
>    Question: What exactly we are looking for, only count? Or we need
> any more logs like for adding database, it should display in which
> server (PG/PPAS) its adding database if this is the case we need a
> feasibility check.

Right now I would like to see the summary updated so it outputs useful
(and correct) information - for example, it could say something like:

=====
Testing completed:

PostgreSQL 9.4:  23 tests passed, 0 tests failed
EPAS 9.5:            25 tests passed, 2 tests failed (foo_test, bar_test)
=====

where PostgreSQL 9.4 and EPAS 9.5 are the two servers configured in
test_config.py and foo_test and bar_test are the names of the tests
that failed.

>> 3) Please ensure that test databases that are created are also dropped
>> again. I'm getting tired of deleting them manually!
>     I already added delete databases in tearDown () function, But
> yeah, I found two test cases where this code missed. I will add this
> in the next patch.

Thanks.

>>
>> Thanks, Dave.
>>
>> On Wed, Jul 27, 2016 at 1:19 PM, Navnath Gadakh
>> <[email protected]> wrote:
>>> Hi Dave,
>>>       We have reproduced the issue you mentioned in the previous
>>> email. We need to skip the login related test cases when SERVER_MODE =
>>> False in the web/config_local.py.
>>>
>>> Please find the revised patch for the same.
>>>
>>> Thanks!
>>>
>>>
>>> On Fri, Jul 22, 2016 at 9:48 PM, Dave Page <[email protected]> wrote:
>>>> Hi
>>>>
>>>> On Fri, Jul 22, 2016 at 2:22 PM, Navnath Gadakh
>>>> <[email protected]> wrote:
>>>>> Hi Dave,
>>>>>
>>>>>    Please find the attached patch for pgAdmin4 unittest(Support of API
>>>>> testing with different servers i.e. PG and PPAS).
>>>>>
>>>>> This patch includes-
>>>>>
>>>>> Test framework support API testing with multiple server for this we need to
>>>>> modify test_config.json(for user it’s test_config.json.in) and
>>>>> test_advanced_config.json(for user it’s test_advanced_config.json.in).
>>>>> Server details of PG and  PPAS are included in both .in files.
>>>>>
>>>>> Removed the logic of logging in  the test client on each test scenario(As
>>>>> per Khushboo's comment in previous email).  We need this logic in test cases
>>>>> under ‘browser/tests/’ as for test scenarios like change password and
>>>>> invalid login test cases as test client should be logged out first. So, as
>>>>> per this the code is slightly modified in ‘browser/tests/’.
>>>>
>>>> OK in principle, but it doesn't seem to work:
>>>>
>>>> This function will add the server under default server group. (Default
>>>> Server Node url) ... ok
>>>>
>>>> ======================================================================
>>>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>>>> This function checks reset password functionality. (TestCase for
>>>> Validating Empty Email)
>>>> ----------------------------------------------------------------------
>>>> Traceback (most recent call last):
>>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>>>> line 44, in runTest
>>>>     'utf-8'))
>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>>>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>>>> should be redirected automatically to target URL: <a href="/">/</a>.
>>>> If not click the link.'
>>>>
>>>> ======================================================================
>>>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>>>> This function checks reset password functionality. (TestCase for
>>>> Validating Invalid_Email)
>>>> ----------------------------------------------------------------------
>>>> Traceback (most recent call last):
>>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>>>> line 44, in runTest
>>>>     'utf-8'))
>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>>>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>>>> should be redirected automatically to target URL: <a href="/">/</a>.
>>>> If not click the link.'
>>>>
>>>> ======================================================================
>>>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>>>> This function checks reset password functionality. (TestCase for
>>>> Validating Valid_Email)
>>>> ----------------------------------------------------------------------
>>>> Traceback (most recent call last):
>>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>>>> line 44, in runTest
>>>>     'utf-8'))
>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>>>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>>>> should be redirected automatically to target URL: <a href="/">/</a>.
>>>> If not click the link.'
>>>>
>>>> ----------------------------------------------------------------------
>>>> Ran 26 tests in 30.109s
>>>>
>>>> FAILED (failures=3)
>>>>
>>>> It's very far from obvious what's wrong here (/reset looks just fine
>>>> to me). How can we get more useful info out of the framework?
>>>>
>>>> --
>>>> Dave Page
>>>> VP, Chief Architect, Tools & Installers
>>>> EnterpriseDB: http://www.enterprisedb.com
>>>> The Enterprise PostgreSQL Company
>>>>
>>>> Blog: http://pgsnake.blogspot.com
>>>> Twitter: @pgsnake
>>>
>>>
>>>
>>> --
>>> Thanks,
>>> Navnath Gadakh
>>> Software Engineer
>>> EnterpriseDB Corporation
>>> Mobile: +91 9975389878
>>
>>
>>
>> --
>> Dave Page
>> VP, Chief Architect, Tools & Installers
>> EnterpriseDB: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>
>
>
> --
> Thanks,
> Navnath Gadakh
> Software Engineer
> EnterpriseDB Corporation
> Mobile: +91 9975389878



-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-01 09:54  Navnath Gadakh <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-08-01 09:54 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,

On Mon, Aug 1, 2016 at 3:17 PM, Dave Page <[email protected]> wrote:
> On Thu, Jul 28, 2016 at 8:12 AM, Navnath Gadakh
> <[email protected]> wrote:
>> Thanks Dave!
>>
>> On Wed, Jul 27, 2016 at 8:12 PM, Dave Page <[email protected]> wrote:
>>> Ahh, that explains it. Nice catch! It's working in both server and
>>> desktop modes now :-).
>>>
>>> I've committed the patch, but can you please look at the following issues:
>>>
>>> 1) When testing SMTP, the encoded password used to connect to the
>>> server is displayed in both the logs and stdout (the "send: 'AUTH
>>> PLAIN ....'" lines). Can you catch that, and replace it with *'s
>>> please? Sooner or later someone will reveal a password otherwise.
        Could you please send me your's regression.log file. While
testing SMTP I didn't see encoded password displayed on both logs and
stdout.
>>>
>>> 2) Is the test count in the summary correct when you have multiple
>>> servers? I think it might be resetting between servers.
>>      In the current code runTest() function calls only one time for
>> single/multiple server/s that's why it's showing same count for both
>> (single & multiple).
>>    Question: What exactly we are looking for, only count? Or we need
>> any more logs like for adding database, it should display in which
>> server (PG/PPAS) its adding database if this is the case we need a
>> feasibility check.
>
> Right now I would like to see the summary updated so it outputs useful
> (and correct) information - for example, it could say something like:
>
> =====
> Testing completed:
>
> PostgreSQL 9.4:  23 tests passed, 0 tests failed
> EPAS 9.5:            25 tests passed, 2 tests failed (foo_test, bar_test)
> =====
>
> where PostgreSQL 9.4 and EPAS 9.5 are the two servers configured in
> test_config.py and foo_test and bar_test are the names of the tests
> that failed.
   Thanks for additional info.
>
>>> 3) Please ensure that test databases that are created are also dropped
>>> again. I'm getting tired of deleting them manually!
>>     I already added delete databases in tearDown () function, But
>> yeah, I found two test cases where this code missed. I will add this
>> in the next patch.
>
> Thanks.
>
>>>
>>> Thanks, Dave.
>>>
>>> On Wed, Jul 27, 2016 at 1:19 PM, Navnath Gadakh
>>> <[email protected]> wrote:
>>>> Hi Dave,
>>>>       We have reproduced the issue you mentioned in the previous
>>>> email. We need to skip the login related test cases when SERVER_MODE =
>>>> False in the web/config_local.py.
>>>>
>>>> Please find the revised patch for the same.
>>>>
>>>> Thanks!
>>>>
>>>>
>>>> On Fri, Jul 22, 2016 at 9:48 PM, Dave Page <[email protected]> wrote:
>>>>> Hi
>>>>>
>>>>> On Fri, Jul 22, 2016 at 2:22 PM, Navnath Gadakh
>>>>> <[email protected]> wrote:
>>>>>> Hi Dave,
>>>>>>
>>>>>>    Please find the attached patch for pgAdmin4 unittest(Support of API
>>>>>> testing with different servers i.e. PG and PPAS).
>>>>>>
>>>>>> This patch includes-
>>>>>>
>>>>>> Test framework support API testing with multiple server for this we need to
>>>>>> modify test_config.json(for user it’s test_config.json.in) and
>>>>>> test_advanced_config.json(for user it’s test_advanced_config.json.in).
>>>>>> Server details of PG and  PPAS are included in both .in files.
>>>>>>
>>>>>> Removed the logic of logging in  the test client on each test scenario(As
>>>>>> per Khushboo's comment in previous email).  We need this logic in test cases
>>>>>> under ‘browser/tests/’ as for test scenarios like change password and
>>>>>> invalid login test cases as test client should be logged out first. So, as
>>>>>> per this the code is slightly modified in ‘browser/tests/’.
>>>>>
>>>>> OK in principle, but it doesn't seem to work:
>>>>>
>>>>> This function will add the server under default server group. (Default
>>>>> Server Node url) ... ok
>>>>>
>>>>> ======================================================================
>>>>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>>>>> This function checks reset password functionality. (TestCase for
>>>>> Validating Empty Email)
>>>>> ----------------------------------------------------------------------
>>>>> Traceback (most recent call last):
>>>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>>>>> line 44, in runTest
>>>>>     'utf-8'))
>>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>>>>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>>>>> should be redirected automatically to target URL: <a href="/">/</a>.
>>>>> If not click the link.'
>>>>>
>>>>> ======================================================================
>>>>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>>>>> This function checks reset password functionality. (TestCase for
>>>>> Validating Invalid_Email)
>>>>> ----------------------------------------------------------------------
>>>>> Traceback (most recent call last):
>>>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>>>>> line 44, in runTest
>>>>>     'utf-8'))
>>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>>>>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>>>>> should be redirected automatically to target URL: <a href="/">/</a>.
>>>>> If not click the link.'
>>>>>
>>>>> ======================================================================
>>>>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>>>>> This function checks reset password functionality. (TestCase for
>>>>> Validating Valid_Email)
>>>>> ----------------------------------------------------------------------
>>>>> Traceback (most recent call last):
>>>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>>>>> line 44, in runTest
>>>>>     'utf-8'))
>>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>>>>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>>>>> should be redirected automatically to target URL: <a href="/">/</a>.
>>>>> If not click the link.'
>>>>>
>>>>> ----------------------------------------------------------------------
>>>>> Ran 26 tests in 30.109s
>>>>>
>>>>> FAILED (failures=3)
>>>>>
>>>>> It's very far from obvious what's wrong here (/reset looks just fine
>>>>> to me). How can we get more useful info out of the framework?
>>>>>
>>>>> --
>>>>> Dave Page
>>>>> VP, Chief Architect, Tools & Installers
>>>>> EnterpriseDB: http://www.enterprisedb.com
>>>>> The Enterprise PostgreSQL Company
>>>>>
>>>>> Blog: http://pgsnake.blogspot.com
>>>>> Twitter: @pgsnake
>>>>
>>>>
>>>>
>>>> --
>>>> Thanks,
>>>> Navnath Gadakh
>>>> Software Engineer
>>>> EnterpriseDB Corporation
>>>> Mobile: +91 9975389878
>>>
>>>
>>>
>>> --
>>> Dave Page
>>> VP, Chief Architect, Tools & Installers
>>> EnterpriseDB: http://www.enterprisedb.com
>>> The Enterprise PostgreSQL Company
>>>
>>> Blog: http://pgsnake.blogspot.com
>>> Twitter: @pgsnake
>>
>>
>>
>> --
>> Thanks,
>> Navnath Gadakh
>> Software Engineer
>> EnterpriseDB Corporation
>> Mobile: +91 9975389878
>
>
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake



-- 
Thanks,
Navnath Gadakh
Software Engineer
EnterpriseDB Corporation
Mobile: +91 9975389878


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-01 10:26  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Dave Page @ 2016-08-01 10:26 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi

On Mon, Aug 1, 2016 at 10:54 AM, Navnath Gadakh
<[email protected]> wrote:
> Hi Dave,
>
> On Mon, Aug 1, 2016 at 3:17 PM, Dave Page <[email protected]> wrote:
>> On Thu, Jul 28, 2016 at 8:12 AM, Navnath Gadakh
>> <[email protected]> wrote:
>>> Thanks Dave!
>>>
>>> On Wed, Jul 27, 2016 at 8:12 PM, Dave Page <[email protected]> wrote:
>>>> Ahh, that explains it. Nice catch! It's working in both server and
>>>> desktop modes now :-).
>>>>
>>>> I've committed the patch, but can you please look at the following issues:
>>>>
>>>> 1) When testing SMTP, the encoded password used to connect to the
>>>> server is displayed in both the logs and stdout (the "send: 'AUTH
>>>> PLAIN ....'" lines). Can you catch that, and replace it with *'s
>>>> please? Sooner or later someone will reveal a password otherwise.
>         Could you please send me your's regression.log file. While
> testing SMTP I didn't see encoded password displayed on both logs and
> stdout.

Here's an extract from stdout (with the encoded password replaced with
xxxxxx). I don't actually see the same in regression.log, but that may
be because of the log settings I'm using - we should filter the same
from there though to be safe:

...
This function checks reset password functionality. (TestCase for
Validating Valid_Email) ... send: 'ehlo
piranha.ox.uk.enterprisedb.com\r\n'
reply: '250-smtp.gmail.com at your service, [194.73.70.210]\r\n'
reply: '250-SIZE 35882577\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH\r\n'
reply: '250-ENHANCEDSTATUSCODES\r\n'
reply: '250-PIPELINING\r\n'
reply: '250-CHUNKING\r\n'
reply: '250 SMTPUTF8\r\n'
reply: retcode (250); Msg: smtp.gmail.com at your service, [194.73.70.210]
SIZE 35882577
8BITMIME
AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
ENHANCEDSTATUSCODES
PIPELINING
CHUNKING
SMTPUTF8
send: 'AUTH PLAIN xxxxxx\r\n'
reply: '235 2.7.0 Accepted\r\n'
reply: retcode (235); Msg: 2.7.0 Accepted
send: u'mail FROM:<no-reply@localhost> size=1122\r\n'
reply: '250 2.1.0 OK v26sm44372678pfi.41 - gsmtp\r\n'
reply: retcode (250); Msg: 2.1.0 OK v26sm44372678pfi.41 - gsmtp
send: u'rcpt TO:<[email protected]>\r\n'
reply: '250 2.1.5 OK v26sm44372678pfi.41 - gsmtp\r\n'
reply: retcode (250); Msg: 2.1.5 OK v26sm44372678pfi.41 - gsmtp
send: 'data\r\n'
reply: '354  Go ahead v26sm44372678pfi.41 - gsmtp\r\n'
reply: retcode (354); Msg: Go ahead v26sm44372678pfi.41 - gsmtp
data: (354, 'Go ahead v26sm44372678pfi.41 - gsmtp')
send: 'Content-Type: multipart/mixed;
boundary="===============5947340609837468105=="\r\nMIME-Version:
1.0\r\nSubject: Password reset instructions for pgAdmin 4\r\nFrom:
no-reply@localhost\r\nTo: [email protected]\r\nDate: Mon, 01 Aug 2016
11:18:01 +0100\r\nMessage-ID:
<[email protected]>\r\n\r\n--===============5947340609837468105==\r\nContent-Type:
multipart/alternative;\r\n
boundary="===============4573645557236154244=="\r\nMIME-Version:
1.0\r\n\r\n--===============4573645557236154244==\r\nContent-Type:
text/plain; charset="utf-8"\r\nMIME-Version:
1.0\r\nContent-Transfer-Encoding: 7bit\r\n\r\nClick the link below to
reset your password:\r\n\r\nhttp://localhost/reset/WyIxIiwiYTY2ODY0ZTY0NzlmMzM1NTNhYTc0NzUwYzEwNDc5ZmQiXQ.CoCzVg.FE0MhiGBwOgVWTcX8mB3Xgq54yw\r\n--===============4573645557236154244==\r\nContent-Type:
text/html; charset="utf-8"\r\nMIME-Version:
1.0\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<p><a
href="http://localhost/reset/WyIxIiwiYTY2ODY0ZTY0NzlmMzM1NTNhYTc0NzUwYzEwNDc5ZmQiXQ.CoCzVg.FE0MhiGBwOgVWTc...
here to reset your
password</a></p>\r\n--===============4573645557236154244==--\r\n\r\n--===============5947340609837468105==--\r\n.\r\n'
reply: '250 2.0.0 OK 1470046685 v26sm44372678pfi.41 - gsmtp\r\n'
reply: retcode (250); Msg: 2.0.0 OK 1470046685 v26sm44372678pfi.41 - gsmtp
data: (250, '2.0.0 OK 1470046685 v26sm44372678pfi.41 - gsmtp')
send: 'quit\r\n'
reply: '221 2.0.0 closing connection v26sm44372678pfi.41 - gsmtp\r\n'
reply: retcode (221); Msg: 2.0.0 closing connection v26sm44372678pfi.41 - gsmtp
ok
runTest (pgadmin.browser.server_groups.servers.tests.test_server_put.ServerUpdateTestCase)
...

These are the relevant settings I'm using:

# Debug mode
DEBUG = True

# App mode
SERVER_MODE = True

# Log
CONSOLE_LOG_LEVEL = DEBUG
FILE_LOG_LEVEL = DEBUG

# Mail server settings
MAIL_SERVER = 'smtp.gmail.com'
MAIL_PORT = 465
MAIL_USE_SSL = True
MAIL_USERNAME = '[email protected]'
MAIL_PASSWORD = 'xxxxxx'


>>>>
>>>> 2) Is the test count in the summary correct when you have multiple
>>>> servers? I think it might be resetting between servers.
>>>      In the current code runTest() function calls only one time for
>>> single/multiple server/s that's why it's showing same count for both
>>> (single & multiple).
>>>    Question: What exactly we are looking for, only count? Or we need
>>> any more logs like for adding database, it should display in which
>>> server (PG/PPAS) its adding database if this is the case we need a
>>> feasibility check.
>>
>> Right now I would like to see the summary updated so it outputs useful
>> (and correct) information - for example, it could say something like:
>>
>> =====
>> Testing completed:
>>
>> PostgreSQL 9.4:  23 tests passed, 0 tests failed
>> EPAS 9.5:            25 tests passed, 2 tests failed (foo_test, bar_test)
>> =====
>>
>> where PostgreSQL 9.4 and EPAS 9.5 are the two servers configured in
>> test_config.py and foo_test and bar_test are the names of the tests
>> that failed.
>    Thanks for additional info.
>>
>>>> 3) Please ensure that test databases that are created are also dropped
>>>> again. I'm getting tired of deleting them manually!
>>>     I already added delete databases in tearDown () function, But
>>> yeah, I found two test cases where this code missed. I will add this
>>> in the next patch.
>>
>> Thanks.
>>
>>>>
>>>> Thanks, Dave.
>>>>
>>>> On Wed, Jul 27, 2016 at 1:19 PM, Navnath Gadakh
>>>> <[email protected]> wrote:
>>>>> Hi Dave,
>>>>>       We have reproduced the issue you mentioned in the previous
>>>>> email. We need to skip the login related test cases when SERVER_MODE =
>>>>> False in the web/config_local.py.
>>>>>
>>>>> Please find the revised patch for the same.
>>>>>
>>>>> Thanks!
>>>>>
>>>>>
>>>>> On Fri, Jul 22, 2016 at 9:48 PM, Dave Page <[email protected]> wrote:
>>>>>> Hi
>>>>>>
>>>>>> On Fri, Jul 22, 2016 at 2:22 PM, Navnath Gadakh
>>>>>> <[email protected]> wrote:
>>>>>>> Hi Dave,
>>>>>>>
>>>>>>>    Please find the attached patch for pgAdmin4 unittest(Support of API
>>>>>>> testing with different servers i.e. PG and PPAS).
>>>>>>>
>>>>>>> This patch includes-
>>>>>>>
>>>>>>> Test framework support API testing with multiple server for this we need to
>>>>>>> modify test_config.json(for user it’s test_config.json.in) and
>>>>>>> test_advanced_config.json(for user it’s test_advanced_config.json.in).
>>>>>>> Server details of PG and  PPAS are included in both .in files.
>>>>>>>
>>>>>>> Removed the logic of logging in  the test client on each test scenario(As
>>>>>>> per Khushboo's comment in previous email).  We need this logic in test cases
>>>>>>> under ‘browser/tests/’ as for test scenarios like change password and
>>>>>>> invalid login test cases as test client should be logged out first. So, as
>>>>>>> per this the code is slightly modified in ‘browser/tests/’.
>>>>>>
>>>>>> OK in principle, but it doesn't seem to work:
>>>>>>
>>>>>> This function will add the server under default server group. (Default
>>>>>> Server Node url) ... ok
>>>>>>
>>>>>> ======================================================================
>>>>>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>>>>>> This function checks reset password functionality. (TestCase for
>>>>>> Validating Empty Email)
>>>>>> ----------------------------------------------------------------------
>>>>>> Traceback (most recent call last):
>>>>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>>>>>> line 44, in runTest
>>>>>>     'utf-8'))
>>>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>>>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>>>>>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>>>>>> should be redirected automatically to target URL: <a href="/">/</a>.
>>>>>> If not click the link.'
>>>>>>
>>>>>> ======================================================================
>>>>>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>>>>>> This function checks reset password functionality. (TestCase for
>>>>>> Validating Invalid_Email)
>>>>>> ----------------------------------------------------------------------
>>>>>> Traceback (most recent call last):
>>>>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>>>>>> line 44, in runTest
>>>>>>     'utf-8'))
>>>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>>>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>>>>>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>>>>>> should be redirected automatically to target URL: <a href="/">/</a>.
>>>>>> If not click the link.'
>>>>>>
>>>>>> ======================================================================
>>>>>> FAIL: runTest (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
>>>>>> This function checks reset password functionality. (TestCase for
>>>>>> Validating Valid_Email)
>>>>>> ----------------------------------------------------------------------
>>>>>> Traceback (most recent call last):
>>>>>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
>>>>>> line 44, in runTest
>>>>>>     'utf-8'))
>>>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in u'<!DOCTYPE
>>>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
>>>>>> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
>>>>>> should be redirected automatically to target URL: <a href="/">/</a>.
>>>>>> If not click the link.'
>>>>>>
>>>>>> ----------------------------------------------------------------------
>>>>>> Ran 26 tests in 30.109s
>>>>>>
>>>>>> FAILED (failures=3)
>>>>>>
>>>>>> It's very far from obvious what's wrong here (/reset looks just fine
>>>>>> to me). How can we get more useful info out of the framework?
>>>>>>
>>>>>> --
>>>>>> Dave Page
>>>>>> VP, Chief Architect, Tools & Installers
>>>>>> EnterpriseDB: http://www.enterprisedb.com
>>>>>> The Enterprise PostgreSQL Company
>>>>>>
>>>>>> Blog: http://pgsnake.blogspot.com
>>>>>> Twitter: @pgsnake
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Thanks,
>>>>> Navnath Gadakh
>>>>> Software Engineer
>>>>> EnterpriseDB Corporation
>>>>> Mobile: +91 9975389878
>>>>
>>>>
>>>>
>>>> --
>>>> Dave Page
>>>> VP, Chief Architect, Tools & Installers
>>>> EnterpriseDB: http://www.enterprisedb.com
>>>> The Enterprise PostgreSQL Company
>>>>
>>>> Blog: http://pgsnake.blogspot.com
>>>> Twitter: @pgsnake
>>>
>>>
>>>
>>> --
>>> Thanks,
>>> Navnath Gadakh
>>> Software Engineer
>>> EnterpriseDB Corporation
>>> Mobile: +91 9975389878
>>
>>
>>
>> --
>> Dave Page
>> VP, Chief Architect, Tools & Installers
>> EnterpriseDB: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>
>
>
> --
> Thanks,
> Navnath Gadakh
> Software Engineer
> EnterpriseDB Corporation
> Mobile: +91 9975389878



-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-02 14:58  Navnath Gadakh <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-08-02 14:58 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,
     Please find the attached patch.
*This patch includes:*
1. API test cases for Roles & Tablespaces node(Completed nodes: server
groups, servers, databases)
    You can run test-suite using following command
     for roles node
               python regression/runtests.py --pkg
browser.server_groups.servers.roles
     for tablespaces node
               python regression/runtests.py --pkg
browser.server_groups.servers.tablespaces
     for all nodes
               python regression/runtests.py
     You can also test with multiple  servers.
2. Delete database code in some of the missed test files.
3. Added advanced configurations in test_advanced_config.json.in for roles
& tablespaces. So, accordingly you need change the file
 test_advanced_config.json
4. Added one test user credentials in test_config.json.in to test the
‘valid password’ test case which is present in
browser/tests/test_change_password.py
    Why test user credentials in test_config.json.in?
           Currently, I am getting ‘UnicodeDecodeError’ when I run
test-suite(runtests.py) with existing code. I already explained the detail
about this error in RM(#1521 <https://redmine.postgresql.org/issues/1521;).
I am creating test user to test the ‘valid password’ test case.

*Notes:*
 1. Code not added to encode the password which is displaying in log file
while testing SMTP(Will add the code in next patch)
 2. Code not added to show enhanced the test summary report(that you
mentioned in the previous email). I will look into this, need to decide
approach what are the code changes required in the current code.

Thanks!


On Mon, Aug 1, 2016 at 3:56 PM, Dave Page <[email protected]>
wrote:

> Hi
>
> On Mon, Aug 1, 2016 at 10:54 AM, Navnath Gadakh
> <[email protected]> wrote:
> > Hi Dave,
> >
> > On Mon, Aug 1, 2016 at 3:17 PM, Dave Page <[email protected]>
> wrote:
> >> On Thu, Jul 28, 2016 at 8:12 AM, Navnath Gadakh
> >> <[email protected]> wrote:
> >>> Thanks Dave!
> >>>
> >>> On Wed, Jul 27, 2016 at 8:12 PM, Dave Page <[email protected]>
> wrote:
> >>>> Ahh, that explains it. Nice catch! It's working in both server and
> >>>> desktop modes now :-).
> >>>>
> >>>> I've committed the patch, but can you please look at the following
> issues:
> >>>>
> >>>> 1) When testing SMTP, the encoded password used to connect to the
> >>>> server is displayed in both the logs and stdout (the "send: 'AUTH
> >>>> PLAIN ....'" lines). Can you catch that, and replace it with *'s
> >>>> please? Sooner or later someone will reveal a password otherwise.
> >         Could you please send me your's regression.log file. While
> > testing SMTP I didn't see encoded password displayed on both logs and
> > stdout.
>
> Here's an extract from stdout (with the encoded password replaced with
> xxxxxx). I don't actually see the same in regression.log, but that may
> be because of the log settings I'm using - we should filter the same
> from there though to be safe:
>
> ...
> This function checks reset password functionality. (TestCase for
> Validating Valid_Email) ... send: 'ehlo
> piranha.ox.uk.enterprisedb.com\r\n'
> reply: '250-smtp.gmail.com at your service, [194.73.70.210]\r\n'
> reply: '250-SIZE 35882577\r\n'
> reply: '250-8BITMIME\r\n'
> reply: '250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER
> XOAUTH\r\n'
> reply: '250-ENHANCEDSTATUSCODES\r\n'
> reply: '250-PIPELINING\r\n'
> reply: '250-CHUNKING\r\n'
> reply: '250 SMTPUTF8\r\n'
> reply: retcode (250); Msg: smtp.gmail.com at your service, [194.73.70.210]
> SIZE 35882577
> 8BITMIME
> AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
> ENHANCEDSTATUSCODES
> PIPELINING
> CHUNKING
> SMTPUTF8
> send: 'AUTH PLAIN xxxxxx\r\n'
> reply: '235 2.7.0 Accepted\r\n'
> reply: retcode (235); Msg: 2.7.0 Accepted
> send: u'mail FROM:<no-reply@localhost> size=1122\r\n'
> reply: '250 2.1.0 OK v26sm44372678pfi.41 - gsmtp\r\n'
> reply: retcode (250); Msg: 2.1.0 OK v26sm44372678pfi.41 - gsmtp
> send: u'rcpt TO:<[email protected]>\r\n'
> reply: '250 2.1.5 OK v26sm44372678pfi.41 - gsmtp\r\n'
> reply: retcode (250); Msg: 2.1.5 OK v26sm44372678pfi.41 - gsmtp
> send: 'data\r\n'
> reply: '354  Go ahead v26sm44372678pfi.41 - gsmtp\r\n'
> reply: retcode (354); Msg: Go ahead v26sm44372678pfi.41 - gsmtp
> data: (354, 'Go ahead v26sm44372678pfi.41 - gsmtp')
> send: 'Content-Type: multipart/mixed;
> boundary="===============5947340609837468105=="\r\nMIME-Version:
> 1.0\r\nSubject: Password reset instructions for pgAdmin 4\r\nFrom:
> no-reply@localhost\r\nTo: [email protected]\r\nDate: Mon, 01 Aug 2016
> 11:18:01 +0100\r\nMessage-ID:
> <[email protected]
> >\r\n\r\n--===============5947340609837468105==\r\nContent-Type:
> multipart/alternative;\r\n
> boundary="===============4573645557236154244=="\r\nMIME-Version:
> 1.0\r\n\r\n--===============4573645557236154244==\r\nContent-Type:
> text/plain; charset="utf-8"\r\nMIME-Version:
> 1.0\r\nContent-Transfer-Encoding: 7bit\r\n\r\nClick the link below to
> reset your
> password:\r\n\r\nhttp://localhost/reset/WyIxIiwiYTY2ODY0ZTY0NzlmMzM1NTNhYTc0NzUwYzEwNDc5ZmQiXQ.CoCzVg.FE0MhiGBwOgVWTcX8mB3Xgq54yw\r\n--===============4573645557236154244==\r\nContent-Type:
> text/html; charset="utf-8"\r\nMIME-Version:
> 1.0\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<p><a
> href="
> http://localhost/reset/WyIxIiwiYTY2ODY0ZTY0NzlmMzM1NTNhYTc0NzUwYzEwNDc5ZmQiXQ.CoCzVg.FE0MhiGBwOgVWTc...
> ">Click
> here to reset your
>
> password</a></p>\r\n--===============4573645557236154244==--\r\n\r\n--===============5947340609837468105==--\r\n.\r\n'
> reply: '250 2.0.0 OK 1470046685 v26sm44372678pfi.41 - gsmtp\r\n'
> reply: retcode (250); Msg: 2.0.0 OK 1470046685 v26sm44372678pfi.41 - gsmtp
> data: (250, '2.0.0 OK 1470046685 v26sm44372678pfi.41 - gsmtp')
> send: 'quit\r\n'
> reply: '221 2.0.0 closing connection v26sm44372678pfi.41 - gsmtp\r\n'
> reply: retcode (221); Msg: 2.0.0 closing connection v26sm44372678pfi.41 -
> gsmtp
> ok
> runTest
> (pgadmin.browser.server_groups.servers.tests.test_server_put.ServerUpdateTestCase)
> ...
>
> These are the relevant settings I'm using:
>
> # Debug mode
> DEBUG = True
>
> # App mode
> SERVER_MODE = True
>
> # Log
> CONSOLE_LOG_LEVEL = DEBUG
> FILE_LOG_LEVEL = DEBUG
>
> # Mail server settings
> MAIL_SERVER = 'smtp.gmail.com'
> MAIL_PORT = 465
> MAIL_USE_SSL = True
> MAIL_USERNAME = '[email protected]'
> MAIL_PASSWORD = 'xxxxxx'
>
>
> >>>>
> >>>> 2) Is the test count in the summary correct when you have multiple
> >>>> servers? I think it might be resetting between servers.
> >>>      In the current code runTest() function calls only one time for
> >>> single/multiple server/s that's why it's showing same count for both
> >>> (single & multiple).
> >>>    Question: What exactly we are looking for, only count? Or we need
> >>> any more logs like for adding database, it should display in which
> >>> server (PG/PPAS) its adding database if this is the case we need a
> >>> feasibility check.
> >>
> >> Right now I would like to see the summary updated so it outputs useful
> >> (and correct) information - for example, it could say something like:
> >>
> >> =====
> >> Testing completed:
> >>
> >> PostgreSQL 9.4:  23 tests passed, 0 tests failed
> >> EPAS 9.5:            25 tests passed, 2 tests failed (foo_test,
> bar_test)
> >> =====
> >>
> >> where PostgreSQL 9.4 and EPAS 9.5 are the two servers configured in
> >> test_config.py and foo_test and bar_test are the names of the tests
> >> that failed.
> >    Thanks for additional info.
> >>
> >>>> 3) Please ensure that test databases that are created are also dropped
> >>>> again. I'm getting tired of deleting them manually!
> >>>     I already added delete databases in tearDown () function, But
> >>> yeah, I found two test cases where this code missed. I will add this
> >>> in the next patch.
> >>
> >> Thanks.
> >>
> >>>>
> >>>> Thanks, Dave.
> >>>>
> >>>> On Wed, Jul 27, 2016 at 1:19 PM, Navnath Gadakh
> >>>> <[email protected]> wrote:
> >>>>> Hi Dave,
> >>>>>       We have reproduced the issue you mentioned in the previous
> >>>>> email. We need to skip the login related test cases when SERVER_MODE
> =
> >>>>> False in the web/config_local.py.
> >>>>>
> >>>>> Please find the revised patch for the same.
> >>>>>
> >>>>> Thanks!
> >>>>>
> >>>>>
> >>>>> On Fri, Jul 22, 2016 at 9:48 PM, Dave Page <
> [email protected]> wrote:
> >>>>>> Hi
> >>>>>>
> >>>>>> On Fri, Jul 22, 2016 at 2:22 PM, Navnath Gadakh
> >>>>>> <[email protected]> wrote:
> >>>>>>> Hi Dave,
> >>>>>>>
> >>>>>>>    Please find the attached patch for pgAdmin4 unittest(Support of
> API
> >>>>>>> testing with different servers i.e. PG and PPAS).
> >>>>>>>
> >>>>>>> This patch includes-
> >>>>>>>
> >>>>>>> Test framework support API testing with multiple server for this
> we need to
> >>>>>>> modify test_config.json(for user it’s test_config.json.in) and
> >>>>>>> test_advanced_config.json(for user it’s
> test_advanced_config.json.in).
> >>>>>>> Server details of PG and  PPAS are included in both .in files.
> >>>>>>>
> >>>>>>> Removed the logic of logging in  the test client on each test
> scenario(As
> >>>>>>> per Khushboo's comment in previous email).  We need this logic in
> test cases
> >>>>>>> under ‘browser/tests/’ as for test scenarios like change password
> and
> >>>>>>> invalid login test cases as test client should be logged out
> first. So, as
> >>>>>>> per this the code is slightly modified in ‘browser/tests/’.
> >>>>>>
> >>>>>> OK in principle, but it doesn't seem to work:
> >>>>>>
> >>>>>> This function will add the server under default server group.
> (Default
> >>>>>> Server Node url) ... ok
> >>>>>>
> >>>>>>
> ======================================================================
> >>>>>> FAIL: runTest
> (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> >>>>>> This function checks reset password functionality. (TestCase for
> >>>>>> Validating Empty Email)
> >>>>>>
> ----------------------------------------------------------------------
> >>>>>> Traceback (most recent call last):
> >>>>>>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> >>>>>> line 44, in runTest
> >>>>>>     'utf-8'))
> >>>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in
> u'<!DOCTYPE
> >>>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
> >>>>>>
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> >>>>>> should be redirected automatically to target URL: <a href="/">/</a>.
> >>>>>> If not click the link.'
> >>>>>>
> >>>>>>
> ======================================================================
> >>>>>> FAIL: runTest
> (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> >>>>>> This function checks reset password functionality. (TestCase for
> >>>>>> Validating Invalid_Email)
> >>>>>>
> ----------------------------------------------------------------------
> >>>>>> Traceback (most recent call last):
> >>>>>>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> >>>>>> line 44, in runTest
> >>>>>>     'utf-8'))
> >>>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in
> u'<!DOCTYPE
> >>>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
> >>>>>>
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> >>>>>> should be redirected automatically to target URL: <a href="/">/</a>.
> >>>>>> If not click the link.'
> >>>>>>
> >>>>>>
> ======================================================================
> >>>>>> FAIL: runTest
> (pgadmin.browser.tests.test_reset_password.ResetPasswordTestCase)
> >>>>>> This function checks reset password functionality. (TestCase for
> >>>>>> Validating Valid_Email)
> >>>>>>
> ----------------------------------------------------------------------
> >>>>>> Traceback (most recent call last):
> >>>>>>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/tests/test_reset_password.py",
> >>>>>> line 44, in runTest
> >>>>>>     'utf-8'))
> >>>>>> AssertionError: 'Recover pgAdmin 4 Password' not found in
> u'<!DOCTYPE
> >>>>>> HTML PUBLIC "-//W3C//DTD HTML 3.2
> >>>>>>
> Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You
> >>>>>> should be redirected automatically to target URL: <a href="/">/</a>.
> >>>>>> If not click the link.'
> >>>>>>
> >>>>>>
> ----------------------------------------------------------------------
> >>>>>> Ran 26 tests in 30.109s
> >>>>>>
> >>>>>> FAILED (failures=3)
> >>>>>>
> >>>>>> It's very far from obvious what's wrong here (/reset looks just fine
> >>>>>> to me). How can we get more useful info out of the framework?
> >>>>>>
> >>>>>> --
> >>>>>> Dave Page
> >>>>>> VP, Chief Architect, Tools & Installers
> >>>>>> EnterpriseDB: http://www.enterprisedb.com
> >>>>>> The Enterprise PostgreSQL Company
> >>>>>>
> >>>>>> Blog: http://pgsnake.blogspot.com
> >>>>>> Twitter: @pgsnake
> >>>>>
> >>>>>
> >>>>>
> >>>>> --
> >>>>> Thanks,
> >>>>> Navnath Gadakh
> >>>>> Software Engineer
> >>>>> EnterpriseDB Corporation
> >>>>> Mobile: +91 9975389878
> >>>>
> >>>>
> >>>>
> >>>> --
> >>>> Dave Page
> >>>> VP, Chief Architect, Tools & Installers
> >>>> EnterpriseDB: http://www.enterprisedb.com
> >>>> The Enterprise PostgreSQL Company
> >>>>
> >>>> Blog: http://pgsnake.blogspot.com
> >>>> Twitter: @pgsnake
> >>>
> >>>
> >>>
> >>> --
> >>> Thanks,
> >>> Navnath Gadakh
> >>> Software Engineer
> >>> EnterpriseDB Corporation
> >>> Mobile: +91 9975389878
> >>
> >>
> >>
> >> --
> >> Dave Page
> >> VP, Chief Architect, Tools & Installers
> >> EnterpriseDB: http://www.enterprisedb.com
> >> The Enterprise PostgreSQL Company
> >>
> >> Blog: http://pgsnake.blogspot.com
> >> Twitter: @pgsnake
> >
> >
> >
> > --
> > Thanks,
> > Navnath Gadakh
> > Software Engineer
> > EnterpriseDB Corporation
> > Mobile: +91 9975389878
>
>
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>



-- 
Thanks,
Navnath Gadakh
Software Engineer
EnterpriseDB Corporation
Mobile: +91 9975389878


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [application/octet-stream] pgadmin_unittest_roles_tablespaces.patch (49.3K, 3-pgadmin_unittest_roles_tablespaces.patch)
  download | inline diff:
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
index 85dcc6c..22cd7ce 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
@@ -38,7 +38,7 @@ class DatabaseAddTestCase(BaseTestGenerator):
         """ This function will add database under 1st server of tree node. """
 
         server_connect_response, server_group, server_ids = \
-            utils.connect_server(self.tester)
+            utils.connect_server(self.tester, True)
 
         for server_connect, server_id in zip(server_connect_response,
                                              server_ids):
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
index 4615d34..6740534 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
@@ -70,5 +70,6 @@ class DatabasesUpdateTestCase(BaseTestGenerator):
         :return: None
         """
 
+        utils.delete_database(self.tester)
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/roles/tests/__init__.py
new file mode 100644
index 0000000..4a11bf8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/__init__.py
@@ -0,0 +1,16 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class RoleGeneratorTestCase(BaseTestGenerator):
+
+    def runTest(self):
+        return
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_add.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_add.py
new file mode 100644
index 0000000..27cae52
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_add.py
@@ -0,0 +1,54 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from regression import test_utils as utils
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class LoginRoleAddTestCase(BaseTestGenerator):
+    """This class has add role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    def setUp(self):
+        """This function used to add the sever"""
+
+        # Add the server
+        utils.add_server(self.tester)
+
+    def runTest(self):
+        """This function test the add role scenario"""
+
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, True)
+
+        for server_connect, server_id in zip(server_connect_response,
+                                             server_ids):
+            if server_connect['data']['connected']:
+                data = utils.get_role_data()
+                response = self.tester.post(self.url + str(server_group) + '/'
+                                            + server_id + '/',
+                                            data=json.dumps(data),
+                                            content_type='html/json')
+                self.assertTrue(response.status_code, 200)
+                response_data = json.loads(response.data.decode('utf-8'))
+                utils.write_role_id(response_data)
+
+    def tearDown(self):
+        """This function deletes the role,server and parent id file"""
+
+        utils.delete_role(self.tester)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_delete.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_delete.py
new file mode 100644
index 0000000..47769cb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_delete.py
@@ -0,0 +1,63 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+
+import json
+from regression import test_utils as utils
+from pgadmin.utils.route import BaseTestGenerator
+from test_setup import config_data
+from regression.test_utils import get_ids
+
+
+class LoginRoleDeleteTestCase(BaseTestGenerator):
+    """This class has delete role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    def setUp(self):
+        """This function used to add the server"""
+
+        # Add the server
+        utils.add_server(self.tester)
+        # Connect to server
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, False)
+        # Add the role
+        utils.add_role(self.tester, server_connect_response, server_group,
+                       server_ids)
+
+    def runTest(self):
+        """This function tests the delete role scenario"""
+
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+        role_ids_dict = all_id["lrid"][0]
+
+        for server_id in server_ids:
+            role_id = role_ids_dict[int(server_id)]
+            role_response = utils.verify_role(self.tester, srv_grp, server_id,
+                                              role_id)
+            if len(role_response) == 0:
+                raise Exception("No roles(s) to delete!!!")
+            response = self.tester.delete(self.url + str(srv_grp) + '/' +
+                                          str(server_id) + '/' + str(role_id),
+                                          follow_redirects=True)
+            delete_response_data = json.loads(response.data.decode('utf-8'))
+            self.assertTrue(delete_response_data['success'], 1)
+
+    def tearDown(self):
+        """This function deletes the role,server and parent id file"""
+
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_get.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_get.py
new file mode 100644
index 0000000..3c2ed9c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_get.py
@@ -0,0 +1,53 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from regression import test_utils as utils
+from test_setup import config_data
+from pgadmin.utils.route import BaseTestGenerator
+from regression.test_utils import get_ids
+
+
+class LoginRoleGetTestCase(BaseTestGenerator):
+    """This class tests the get role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    def setUp(self):
+        # Add the server
+        utils.add_server(self.tester)
+        # Connect to server
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, False)
+        # Add the role
+        utils.add_role(self.tester, server_connect_response, server_group,
+                       server_ids)
+
+    def runTest(self):
+        """This function test the get role scenario"""
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+        role_ids_dict = all_id["lrid"][0]
+
+        for server_id in server_ids:
+            role_id = role_ids_dict[int(server_id)]
+            response = self.tester.get(self.url + str(srv_grp) + '/' +
+                                       str(server_id) + '/' + str(role_id),
+                                       follow_redirects=True)
+            self.assertEquals(response.status_code, 200)
+
+    def tearDown(self):
+        """This function deletes the role,server and parent id file"""
+
+        utils.delete_role(self.tester)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_put.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_put.py
new file mode 100644
index 0000000..b1f8ba2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_put.py
@@ -0,0 +1,68 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from regression import test_utils as utils
+from test_setup import config_data, advanced_config_data
+from pgadmin.utils.route import BaseTestGenerator
+from regression.test_utils import get_ids
+
+
+class LoginRolePutTestCase(BaseTestGenerator):
+    """This class has update role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    def setUp(self):
+        # Add the server
+        utils.add_server(self.tester)
+        # Connect to server
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, False)
+        # Add the role
+        utils.add_role(self.tester, server_connect_response, server_group,
+                       server_ids)
+
+    def runTest(self):
+        """This function tests the update role data scenario"""
+
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+        role_ids_dict = all_id["lrid"][0]
+
+        for server_id in server_ids:
+            role_id = role_ids_dict[int(server_id)]
+            role_response = utils.verify_role(self.tester, srv_grp, server_id,
+                                              role_id)
+            if len(role_response) == 0:
+                raise Exception("No roles(s) to update!!!")
+
+            data = {
+                "description": advanced_config_data["test_lr_update_data"]
+                ["test_comment"],
+                "lrid": role_id
+            }
+            put_response = self.tester.put(self.url + str(srv_grp) + '/' +
+                                           str(server_id) + '/' + str(role_id),
+                                           data=json.dumps(data),
+                                           follow_redirects=True)
+
+            self.assertEquals(put_response.status_code, 200)
+
+    def tearDown(self):
+        """This function deletes the role,server and parent id file"""
+
+        utils.delete_role(self.tester)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/__init__.py
new file mode 100644
index 0000000..3302027
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/__init__.py
@@ -0,0 +1,16 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class TblspaceGeneratorTestCase(BaseTestGenerator):
+
+    def runTest(self):
+        return
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py
new file mode 100644
index 0000000..48c7628
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py
@@ -0,0 +1,53 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from regression import test_utils as utils
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class TableSpaceAddTestCase(BaseTestGenerator):
+    """This class will add tablespace node under server"""
+
+    scenarios = [
+        # Fetching default URL for tablespace node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    def setUp(self):
+        """This function used to add the sever"""
+
+        # Add the server
+        utils.add_server(self.tester)
+
+    def runTest(self):
+        """This function test the add tablespace scenario"""
+
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, True)
+
+        for server_connect, server_id in zip(server_connect_response,
+                                             server_ids):
+            if server_connect['data']['connected']:
+                data = utils.get_tablespace_data(server_connect)
+                response = self.tester.post(self.url + str(server_group) + '/'
+                                            + server_id + '/',
+                                            data=json.dumps(data),
+                                            content_type='html/json')
+                self.assertTrue(response.status_code, 200)
+                response_data = json.loads(response.data.decode('utf-8'))
+                utils.write_tablespace_id(response_data)
+
+    def tearDown(self):
+        """This function deletes the tablespace,server and parent id file"""
+
+        utils.delete_table_space(self.tester)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py
new file mode 100644
index 0000000..298a8e8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py
@@ -0,0 +1,65 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+from regression import test_utils as utils
+from pgadmin.utils.route import BaseTestGenerator
+from test_setup import config_data
+from regression.test_utils import get_ids
+
+
+class TableSpaceDeleteTestCase(BaseTestGenerator):
+    """This class has delete table space scenario"""
+
+    scenarios = [
+        # Fetching default URL for tablespace node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    def setUp(self):
+        """This function used to add the server"""
+
+        # Add the server
+        utils.add_server(self.tester)
+        # Connect to server
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, False)
+        # Add the table space
+        utils.add_table_space(self.tester, server_connect_response,
+                              server_group,
+                              server_ids)
+
+    def runTest(self):
+        """This function tests the delete table space scenario"""
+
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+        table_space_ids_dict = all_id["table_space_id"][0]
+
+        for server_id in server_ids:
+            table_space_id = table_space_ids_dict[int(server_id)]
+            table_space_response = utils.verify_table_space(self.tester,
+                                                            srv_grp, server_id,
+                                                            table_space_id)
+            if len(table_space_response) == 0:
+                raise Exception("No tablespace(s) to delete!!!")
+
+            response = self.tester.delete(self.url + str(srv_grp) + '/' +
+                                          str(server_id) + '/' + str(
+                table_space_id),
+                                          follow_redirects=True)
+            delete_response_data = json.loads(response.data.decode('utf-8'))
+            self.assertTrue(delete_response_data['success'], 1)
+
+    def tearDown(self):
+        """This function deletes the server and parent id file"""
+
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py
new file mode 100644
index 0000000..45e12c0
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py
@@ -0,0 +1,59 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from regression import test_utils as utils
+from test_setup import config_data
+from pgadmin.utils.route import BaseTestGenerator
+from regression.test_utils import get_ids
+
+
+class TablespaceGetTestCase(BaseTestGenerator):
+    """This class tests the get table space scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    def setUp(self):
+        # Add the server
+        utils.add_server(self.tester)
+        # Connect to server
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, False)
+        # Add the table space
+        utils.add_table_space(self.tester, server_connect_response,
+                              server_group,
+                              server_ids)
+
+    def runTest(self):
+        """This function test the get table space scenario"""
+
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+        tablespace_ids_dict = all_id["table_space_id"][0]
+
+        for server_id in server_ids:
+            tablespace_id = tablespace_ids_dict[int(server_id)]
+            server_response = utils.verify_server(self.tester, srv_grp,
+                                                  server_id)
+            if server_response['data']['connected']:
+                response = self.tester.get(self.url + str(srv_grp) + '/' +
+                                           str(server_id) + '/' + str(
+                    tablespace_id),
+                                           follow_redirects=True)
+                self.assertEquals(response.status_code, 200)
+
+    def tearDown(self):
+        """This function deletes the role,server and parent id file"""
+
+        utils.delete_table_space(self.tester)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py
new file mode 100644
index 0000000..927640f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py
@@ -0,0 +1,72 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from regression import test_utils as utils
+from test_setup import config_data, advanced_config_data
+from pgadmin.utils.route import BaseTestGenerator
+from regression.test_utils import get_ids
+
+
+class TableSpaceUpdateTestCase(BaseTestGenerator):
+    """This class has update tablespace scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    def setUp(self):
+        # Add the server
+        utils.add_server(self.tester)
+        # Connect to server
+        server_connect_response, server_group, server_ids = \
+            utils.connect_server(self.tester, False)
+        # Add the tablespace
+        utils.add_table_space(self.tester, server_connect_response,
+                              server_group,
+                              server_ids)
+
+    def runTest(self):
+        """This function tests the update tablespace data scenario"""
+
+        srv_grp = config_data['test_server_group']
+        all_id = get_ids()
+        server_ids = all_id["sid"]
+        tablespace_ids_dict = all_id["table_space_id"][0]
+
+        for server_id in server_ids:
+            tablespace_id = tablespace_ids_dict[int(server_id)]
+            tablespace_response = utils.verify_table_space(self.tester,
+                                                           srv_grp, server_id,
+                                                           tablespace_id)
+            if len(tablespace_response) == 0:
+                raise Exception("No tablespace(s) to update!!!")
+
+            data = {
+                "description": advanced_config_data["test_tbspc_update_data"]
+                ["test_comment"],
+                "table_space_id": tablespace_id
+            }
+
+            put_response = self.tester.put(self.url + str(srv_grp) + '/' +
+                                           str(server_id) + '/' + str(
+                tablespace_id),
+                                           data=json.dumps(data),
+                                           follow_redirects=True)
+
+            self.assertEquals(put_response.status_code, 200)
+
+    def tearDown(self):
+        """This function deletes the role,server and parent id file"""
+
+        utils.delete_table_space(self.tester)
+        utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
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 2b1eb45..37d6949 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
@@ -32,10 +32,8 @@ class ServersAddTestCase(BaseTestGenerator):
             url = "{0}{1}/".format(self.url, server_group)
             response = self.tester.post(url, data=json.dumps(server_data),
                                         content_type='html/json')
-
             self.assertTrue(response.status_code, 200)
-
-            response_data = json.loads(response.data.decode())
+            response_data = json.loads(response.data.decode('utf-8'))
             utils.write_parent_id(response_data, pickle_id_dict)
 
     def tearDown(self):
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
index 5e810ba..9973359 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
@@ -68,5 +68,6 @@ class ServerUpdateTestCase(BaseTestGenerator):
         :return: None
         """
 
+        utils.delete_database(self.tester)
         utils.delete_server(self.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/tests/test_change_password.py b/web/pgadmin/browser/tests/test_change_password.py
index 2f714a7..3dbd386 100644
--- a/web/pgadmin/browser/tests/test_change_password.py
+++ b/web/pgadmin/browser/tests/test_change_password.py
@@ -11,6 +11,8 @@ import uuid
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression.test_setup import config_data
+from regression import test_utils as utils
+from utils import change_password
 
 
 class ChangePasswordTestCase(BaseTestGenerator):
@@ -56,51 +58,58 @@ class ChangePasswordTestCase(BaseTestGenerator):
                 ['test_new_password']),
             respdata='Invalid password')),
 
-        # This testcase checks for valid password
+        # This test case checks for valid password
         ('TestCase for Changing Valid_Password', dict(
-            password=(config_data['pgAdmin4_login_credentials']
+            valid_password='reassigning_password',
+            username=(config_data['pgAdmin4_test_user_credentials']
+                      ['test_login_username']),
+            password=(config_data['pgAdmin4_test_user_credentials']
                       ['test_login_password']),
-            new_password=(config_data['pgAdmin4_login_credentials']
+            new_password=(config_data['pgAdmin4_test_user_credentials']
                           ['test_new_password']),
             new_password_confirm=(
-                config_data['pgAdmin4_login_credentials']
+                config_data['pgAdmin4_test_user_credentials']
                 ['test_new_password']),
-            respdata='You successfully changed your password.')),
-        ('Reassigning_Password', dict(
-            test_case='reassigning_password',
-            password=(config_data['pgAdmin4_login_credentials']
-                      ['test_new_password']),
-            new_password=(config_data['pgAdmin4_login_credentials']
-                          ['test_login_password']),
-            new_password_confirm=(
-                config_data['pgAdmin4_login_credentials']
-                ['test_login_password']),
             respdata='You successfully changed your password.'))
-
     ]
 
+    def setUp(self):
+        pass
+
     def runTest(self):
         """This function will check change password functionality."""
 
-        # Check for 'test_case' exists in self For reassigning the password.
-        # Password gets change in change password test case.
-        if 'test_case' in dir(self):
-            email = \
-                config_data['pgAdmin4_login_credentials'][
-                    'test_login_username']
-            password = \
-                config_data['pgAdmin4_login_credentials'][
-                    'test_new_password']
+        # Check for 'valid_password' exists in self to test 'valid password'
+        # test case
+        if 'valid_password' in dir(self):
+            response = self.tester.post('/user_management/user/', data=dict(
+                email=self.username, newPassword=self.password,
+                confirmPassword=self.password, active=1, role="2"),
+                                        follow_redirects=True)
+            assert response.status_code == 200
+
+            # Logout the Administrator before login normal user
+            utils.logout_tester_account(self.tester)
+
             response = self.tester.post('/login', data=dict(
-                email=email, password=password), follow_redirects=True)
-
-        response = self.tester.get('/change', follow_redirects=True)
-        self.assertIn('pgAdmin 4 Password Change', response.data.decode(
-            'utf-8'))
-
-        response = self.tester.post('/change', data=dict(
-            password=self.password,
-            new_password=self.new_password,
-            new_password_confirm=self.new_password_confirm),
-                                    follow_redirects=True)
-        self.assertIn(self.respdata, response.data.decode('utf-8'))
+                email=self.username, password=self.password),
+                                        follow_redirects=True)
+            assert response.status_code == 200
+
+            # test the 'change password' test case
+            change_password(self)
+
+            # Delete the normal user after changing it's password
+            utils.logout_tester_account(self.tester)
+
+            # Login the Administrator before deleting normal user
+            utils.login_tester_account(self.tester)
+            response = self.tester.delete('/user_management/user/2',
+                                          follow_redirects=True)
+            assert response.status_code == 200
+        else:
+            change_password(self)
+
+    def tearDown(self):
+        utils.login_tester_account(self.tester)
+
diff --git a/web/pgadmin/browser/tests/utils.py b/web/pgadmin/browser/tests/utils.py
new file mode 100644
index 0000000..18548ce
--- /dev/null
+++ b/web/pgadmin/browser/tests/utils.py
@@ -0,0 +1,21 @@
+# ##########################################################################
+#
+# #pgAdmin 4 - PostgreSQL Tools
+#
+# #Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# #This software is released under the PostgreSQL Licence
+#
+# ##########################################################################
+
+
+def change_password(self):
+    response = self.tester.get('/change', follow_redirects=True)
+    self.assertIn('pgAdmin 4 Password Change', response.data.decode(
+        'utf-8'))
+
+    response = self.tester.post('/change', data=dict(
+        password=self.password,
+        new_password=self.new_password,
+        new_password_confirm=self.new_password_confirm),
+                                follow_redirects=True)
+    self.assertIn(self.respdata, response.data.decode('utf-8'))
\ No newline at end of file
diff --git a/web/regression/test_advanced_config.json.in b/web/regression/test_advanced_config.json.in
index c0d278b..8b679ad 100644
--- a/web/regression/test_advanced_config.json.in
+++ b/web/regression/test_advanced_config.json.in
@@ -194,6 +194,50 @@
   {
       "test_comment": "This is db update comment"
   }
- ]
+ ],
+ "test_lr_credentials": {
+      "test_can_login": "true",
+      "test_conn_limit": -1,
+      "test_create_role": "true",
+      "test_role_inherit": "true",
+      "test_role_membership": [],
+      "test_lr_name":  "testlrg1",
+      "test_lr_password": "edb",
+      "test_lr_validity": "12/27/2016",
+      "test_sec_lable": [],
+      "test_variable":[
+                        {"name":"work_mem",
+                          "database":"postgres",
+                          "value":65
+                        }]
+    },
+  "test_lr_update_data": {
+      "test_comment": "This is db update comment"
+  },
+
+  "test_tablespc_credentials":[{
+    "test_tblspace_name": "test_tablespace",
+    "test_spc_seclable": [],
+    "test_spc_acl": [
+      {
+        "grantee":"postgres",
+        "grantor":"postgres",
+        "privileges":[
+          {
+            "privilege_type":"C",
+            "privilege":true,
+            "with_grant":false
+          }
+        ]
+      }
+    ],
+    "test_spc_location": "/Library/PostgreSQL/9.6/data",
+    "test_spc_opts": [],
+    "test_spc_user": "postgres"
+  }],
+
+    "test_tbspc_update_data": {
+    "test_comment": "This is tablespace update comment"
+  }
 
-}
\ No newline at end of file
+}
diff --git a/web/regression/test_config.json.in b/web/regression/test_config.json.in
index 028d1e7..9fcf197 100644
--- a/web/regression/test_config.json.in
+++ b/web/regression/test_config.json.in
@@ -4,6 +4,11 @@
     "test_login_password": "PASSWORD",
     "test_login_username": "[email protected]"
   },
+  "pgAdmin4_test_user_credentials": {
+    "test_new_password": "NEWPASSWORD",
+    "test_login_password": "PASSWORD",
+    "test_login_username": "[email protected]"
+  },
   "test_server_group": 1,
   "test_server_credentials": [
     {
diff --git a/web/regression/test_utils.py b/web/regression/test_utils.py
index 6be2bb2..18c5981 100644
--- a/web/regression/test_utils.py
+++ b/web/regression/test_utils.py
@@ -19,6 +19,20 @@ SERVER_URL = '/browser/server/obj/'
 SERVER_CONNECT_URL = 'browser/server/connect/'
 DATABASE_URL = '/browser/database/obj/'
 DATABASE_CONNECT_URL = 'browser/database/connect/'
+ROLE_URL = '/browser/role/obj/'
+TABLE_SPACE_URL = '/browser/tablespace/obj/'
+
+
+def get_pickle_id_dict():
+    """This function returns the empty dict of server config data"""
+
+    pickle_id_dict = {
+        "sid": [],  # server
+        "did": [],  # database
+        "lrid": [],  # role
+        "table_space_id": []  # tablespace
+    }
+    return pickle_id_dict
 
 
 def get_ids(url=pickle_path):
@@ -34,10 +48,22 @@ def get_ids(url=pickle_path):
     output = open(url, 'rb')
     ids = pickle.load(output)
     output.close()
-
     return ids
 
 
+def verify_server(tester, server_group, server_id):
+    """This function verifies that server is connecting or not"""
+
+    response = tester.post(
+        '{0}{1}/{2}'.format(SERVER_CONNECT_URL, server_group, server_id),
+        data=dict(password=config_data
+        ['test_server_credentials'][0]
+        ['test_db_password']),
+        follow_redirects=True)
+    srv_connect = json.loads(response.data.decode('utf-8'))
+    return srv_connect
+
+
 def verify_database(tester, server_group, server_id, db_id):
     """
     This function verifies that database is exists and whether it connect
@@ -158,6 +184,7 @@ def logout_tester_account(tester):
     response = tester.get('/logout')
 
 
+# Config data for parent_id.pkl
 def get_config_data():
     """
     This function get the data related to server group and database
@@ -168,12 +195,7 @@ def get_config_data():
     """
 
     db_data = []
-
-    pickle_id_dict = {
-        "sid": [],  # server
-        "did": []  # database
-    }
-
+    pickle_id_dict = get_pickle_id_dict()
     server_group = config_data['test_server_group']
 
     for srv in config_data['test_server_credentials']:
@@ -205,7 +227,7 @@ def write_parent_id(response_data, pickle_id_dict):
         existed_server_id = open(pickle_path, 'rb')
         pickle_id_dict = pickle.load(existed_server_id)
 
-    pickle_id_dict["sid"].append(server_id)
+    pickle_id_dict["sid"].append(str(server_id))
     output = open(pickle_path, 'wb')
     pickle.dump(pickle_id_dict, output)
     output.close()
@@ -223,20 +245,22 @@ def write_db_parent_id(response_data):
 
     db_id = response_data['node']['_id']
     server_id = response_data['node']['_pid']
+    # TODO: modify logic to write in file / file exists or create new
+    pickle_id_dict = get_pickle_id_dict()
     if os.path.isfile(pickle_path):
         existing_server_id = open(pickle_path, 'rb')
         tol_server_id = pickle.load(existing_server_id)
         pickle_id_dict = tol_server_id
-        if 'did' in pickle_id_dict:
-            if pickle_id_dict['did']:
-                # Add the db_id as value in dict
-                pickle_id_dict["did"][0].update({server_id: db_id})
-            else:
-                # Create new dict with server_id and db_id
-                pickle_id_dict["did"].append({server_id: db_id})
-        db_output = open(pickle_path, 'wb')
-        pickle.dump(pickle_id_dict, db_output)
-        db_output.close()
+    if 'did' in pickle_id_dict:
+        if pickle_id_dict['did']:
+            # Add the db_id as value in dict
+            pickle_id_dict["did"][0].update({server_id: db_id})
+        else:
+            # Create new dict with server_id and db_id
+            pickle_id_dict["did"].append({server_id: db_id})
+    db_output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, db_output)
+    db_output.close()
 
 
 def delete_parent_id_file():
@@ -265,7 +289,7 @@ def add_server(tester):
     for db_detail in db_data:
         response = tester.post(url, data=json.dumps(db_detail),
                                content_type='html/json')
-        response_data = json.loads(response.data.decode())
+        response_data = json.loads(response.data.decode('utf-8'))
         write_parent_id(response_data, pickle_id_dict)
 
 
@@ -289,12 +313,14 @@ def get_server(tester):
         response_data = json.loads(response.data.decode())
 
 
-def connect_server(tester):
+def connect_server(tester, add_db_flag=False):
     """
     This function used to connect added server
 
     :param tester:test client object
     :type tester: flask test object
+    :param add_db_flag: flag for db add test case
+    :type add_db_flag: bool
     :return: server_connect, server_group, server_id
     :rtype: server_connect:dict, server_group:dict, server_id:str
     """
@@ -315,9 +341,10 @@ def connect_server(tester):
                                    ['test_server_credentials'][0]
                                    ['test_db_password']),
                                follow_redirects=True)
-        server_connect_detail = json.loads(response.data.decode())
-        connect_database(tester, server_connect_detail, server_id,
-                         server_group)
+        server_connect_detail = json.loads(response.data.decode('utf-8'))
+        if not add_db_flag:
+            connect_database(tester, server_connect_detail, server_id,
+                             server_group)
         server_connect.append(server_connect_detail)
         servers.append(server_id)
     return server_connect, server_group, servers
@@ -345,7 +372,7 @@ def connect_database(tester, server_connect, server_id, server_group):
             DATABASE_URL + str(server_group) + "/" + server_id + "/",
             data=json.dumps(db_data),
             content_type='html/json')
-        response_data = json.loads(db_response.data.decode())
+        response_data = json.loads(db_response.data.decode('utf-8'))
         write_db_parent_id(response_data)
 
 
@@ -366,7 +393,7 @@ def delete_server(tester):
     for server_id in server_ids:
         response = tester.delete(url + str(server_id))
         assert response.status_code == 200
-        response_data = json.loads(response.data.decode())
+        response_data = json.loads(response.data.decode('utf-8'))
         assert response_data['success'] == 1
 
 
@@ -395,3 +422,309 @@ def delete_database(tester):
         assert response.status_code == 200
         response_data = json.loads(response.data.decode('utf-8'))
         assert response_data['success'] == 1
+
+
+# Roles utility
+def verify_role(tester, server_group, server_id, role_id):
+    """
+    This function calls the GET API for role to verify
+
+    :param tester: test client
+    :type tester: flask test client object
+    :param server_group: server group id
+    :type server_group: int
+    :param server_id: server id
+    :type server_id: str
+    :param role_id: role id
+    :type role_id: int
+    :return: dict/None
+    """
+
+    response = tester.post(
+        '{0}{1}/{2}'.format(SERVER_CONNECT_URL, server_group, server_id),
+        data=dict(password=config_data
+        ['test_server_credentials'][0]
+        ['test_db_password']),
+        follow_redirects=True)
+    srv_connect = json.loads(response.data.decode('utf-8'))
+    if srv_connect['data']['connected']:
+        response = tester.get(
+            '{0}{1}/{2}/{3}'.format(ROLE_URL, server_group, server_id,
+                                    role_id),
+            content_type='html/json')
+        temp_response = json.loads(response.data.decode('utf-8'))
+        return temp_response
+    else:
+        return None
+
+
+def test_getrole(tester):
+    if not tester:
+        return None
+
+    all_id = get_ids()
+
+    server_ids = all_id["sid"]
+    role_ids_dict = all_id["lrid"][0]
+    server_group = config_data['test_server_group']
+
+    role_response_data = []
+    for server_id in server_ids:
+        role_id = role_ids_dict[int(server_id)]
+        role_response_data.append(
+            verify_role(tester, server_group, server_id, role_id))
+    return role_response_data
+
+
+def get_role_data():
+    """This function returns the role data from config file"""
+
+    data = {
+        "rolcanlogin": advanced_config_data['test_lr_credentials']
+        ['test_can_login'],
+        "rolconnlimit": advanced_config_data['test_lr_credentials']
+        ['test_conn_limit'],
+        "rolcreaterole": advanced_config_data['test_lr_credentials']
+        ['test_create_role'],
+        "rolinherit": advanced_config_data['test_lr_credentials']
+        ['test_role_inherit'],
+        "rolmembership": advanced_config_data['test_lr_credentials']
+        ['test_role_membership'],
+        "rolname": str(uuid.uuid4())[1:8],
+        "rolpassword": advanced_config_data['test_lr_credentials']
+        ['test_lr_password'],
+        "rolvaliduntil": advanced_config_data['test_lr_credentials']
+        ['test_lr_validity'],
+        "seclabels": advanced_config_data['test_lr_credentials']
+        ['test_sec_lable'],
+        "variables": advanced_config_data['test_lr_credentials']
+        ['test_variable']
+    }
+    return data
+
+
+def add_role(tester, server_connect_response, server_group, server_ids):
+    """
+    This function is used to add the roles to server
+
+    :param tester: flask test client
+    :type tester: flask test client object
+    :param server_connect_response: server connect API response
+    :type server_connect_response: dict
+    :param server_group: server group
+    :type server_group: int
+    :param server_ids: list of server id
+    :type server_ids: list
+    :return: None
+    """
+
+    for server_connect, server_id in zip(server_connect_response,
+                                         server_ids):
+        if server_connect['data']['connected']:
+            data = get_role_data()
+            response = tester.post(ROLE_URL + str(server_group) + '/'
+                                   + server_id + '/', data=json.dumps(data),
+                                   content_type='html/json')
+            assert response.status_code == 200
+            response_data = json.loads(response.data.decode('utf-8'))
+            write_role_id(response_data)
+
+
+def write_role_id(response_data):
+    """
+
+    :param response_data:
+    :return:
+    """
+
+    lr_id = response_data['node']['_id']
+    server_id = response_data['node']['_pid']
+    pickle_id_dict = get_pickle_id_dict()
+    # TODO: modify logic to write in file / file exists or create new check
+    # old file
+    if os.path.isfile(pickle_path):
+        existing_server_id = open(pickle_path, 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+    if 'lrid' in pickle_id_dict:
+        if pickle_id_dict['lrid']:
+            # Add the db_id as value in dict
+            pickle_id_dict["lrid"][0].update({server_id: lr_id})
+        else:
+            # Create new dict with server_id and db_id
+            pickle_id_dict["lrid"].append({server_id: lr_id})
+    db_output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, db_output)
+    db_output.close()
+
+
+def delete_role(tester):
+    """
+    This function use to delete the existing roles in the servers
+
+    :param tester: flask test client
+    :type tester: flask test object
+    :return: None
+    """
+
+    srv_grp = config_data['test_server_group']
+    all_id = get_ids()
+    server_ids = all_id["sid"]
+    role_ids_dict = all_id["lrid"][0]
+
+    for server_id in server_ids:
+        role_id = role_ids_dict[int(server_id)]
+        role_response = verify_role(tester, srv_grp, server_id,
+                                    role_id)
+        if len(role_response) == 0:
+            raise Exception("No roles(s) to delete!!!")
+        response = tester.delete(ROLE_URL + str(srv_grp) + '/' +
+                                 str(server_id) + '/' + str(role_id),
+                                 follow_redirects=True)
+        assert response.status_code == 200
+        delete_response_data = json.loads(response.data.decode('utf-8'))
+        assert delete_response_data['success'] == 1
+
+
+# Tablespace utility
+def get_tablespace_data(server_connect):
+    """This function returns the tablespace data from config file"""
+
+    adv_config_data = None
+    data = None
+    db_user = server_connect['data']['user']['name']
+
+    # Get the config data of appropriate db user
+    for config_test_data in advanced_config_data['test_tablespc_credentials']:
+        if db_user == config_test_data['test_spc_user']:
+            adv_config_data = config_test_data
+
+    if adv_config_data is not None:
+        data = {
+            "name": str(uuid.uuid4())[1:8],
+            "seclabels": adv_config_data["test_spc_seclable"],
+            "spcacl": adv_config_data["test_spc_acl"],
+            "spclocation": adv_config_data["test_spc_location"],
+            "spcoptions": adv_config_data["test_spc_opts"],
+            "spcuser": adv_config_data["test_spc_user"]
+        }
+    return data
+
+
+def write_tablespace_id(response_data):
+    """
+    This function write the table space id to parent_id.pkl
+
+    :param response_data: create table space API response data
+    :type response_data: dict
+    :return: None
+    """
+
+    table_space_id = response_data['node']['_id']
+    server_id = response_data['node']['_pid']
+    pickle_id_dict = get_pickle_id_dict()
+    if os.path.isfile(pickle_path):
+        existing_server_id = open(pickle_path, 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+    if 'table_space_id' in pickle_id_dict:
+        if pickle_id_dict['table_space_id']:
+            # Add the db_id as value in dict
+            pickle_id_dict["table_space_id"][0].update(
+                {server_id: table_space_id})
+        else:
+            # Create new dict with server_id and db_id
+            pickle_id_dict["table_space_id"].append(
+                {server_id: table_space_id})
+    db_output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, db_output)
+    db_output.close()
+
+
+def add_table_space(tester, server_connect_response, server_group, server_ids):
+    """
+    This function is used to add the roles to server
+
+    :param tester: flask test client
+    :type tester: flask test client object
+    :param server_connect_response: server connect API response
+    :type server_connect_response: dict
+    :param server_group: server group
+    :type server_group: int
+    :param server_ids: list of server id
+    :type server_ids: list
+    :return: None
+    """
+
+    for server_connect, server_id in zip(server_connect_response,
+                                         server_ids):
+        if server_connect['data']['connected']:
+            data = get_tablespace_data(server_connect)
+            response = tester.post(TABLE_SPACE_URL + str(server_group) + '/'
+                                   + server_id + '/',
+                                   data=json.dumps(data),
+                                   content_type='html/json')
+            assert response.status_code == 200
+            response_data = json.loads(response.data.decode('utf-8'))
+            write_tablespace_id(response_data)
+
+
+def verify_table_space(tester, server_group, server_id, tablespace_id):
+    """
+    This function calls the GET API for role to verify
+
+    :param tester: test client
+    :type tester: flask test client object
+    :param server_group: server group id
+    :type server_group: int
+    :param server_id: server id
+    :type server_id: str
+    :param tablespace_id: table space id
+    :type tablespace_id: int
+    :return: dict/None
+    """
+
+    response = tester.post(
+        '{0}{1}/{2}'.format(SERVER_CONNECT_URL, server_group, server_id),
+        data=dict(password=config_data
+        ['test_server_credentials'][0]
+        ['test_db_password']),
+        follow_redirects=True)
+    srv_connect = json.loads(response.data.decode('utf-8'))
+    if srv_connect['data']['connected']:
+        response = tester.get(
+            '{0}{1}/{2}/{3}'.format(TABLE_SPACE_URL, server_group, server_id,
+                                    tablespace_id),
+            content_type='html/json')
+        temp_response = json.loads(response.data.decode('utf-8'))
+        return temp_response
+    else:
+        return None
+
+
+def delete_table_space(tester):
+    """
+    This function use to delete the existing tablespace in the servers
+
+    :param tester: flask test client
+    :type tester: flask test object
+    :return: None
+    """
+
+    srv_grp = config_data['test_server_group']
+    all_id = get_ids()
+    server_ids = all_id["sid"]
+    tablespace_ids_dict = all_id["table_space_id"][0]
+
+    for server_id in server_ids:
+        tablespace_id = tablespace_ids_dict[int(server_id)]
+        role_response = verify_table_space(tester, srv_grp, server_id,
+                                           tablespace_id)
+        if len(role_response) == 0:
+            raise Exception("No tablespace(s) to delete!!!")
+        response = tester.delete(TABLE_SPACE_URL + str(srv_grp) + '/' +
+                                 str(server_id) + '/' + str(tablespace_id),
+                                 follow_redirects=True)
+        assert response.status_code == 200
+        delete_response_data = json.loads(response.data.decode('utf-8'))
+        assert delete_response_data['success'] == 1


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-03 09:15  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Dave Page @ 2016-08-03 09:15 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Navnath

On Tue, Aug 2, 2016 at 3:58 PM, Navnath Gadakh
<[email protected]> wrote:
> Hi Dave,
>      Please find the attached patch.
> This patch includes:
> 1. API test cases for Roles & Tablespaces node(Completed nodes: server
> groups, servers, databases)
>     You can run test-suite using following command
>      for roles node
>                python regression/runtests.py --pkg
> browser.server_groups.servers.roles
>      for tablespaces node
>                python regression/runtests.py --pkg
> browser.server_groups.servers.tablespaces
>      for all nodes
>                python regression/runtests.py
>      You can also test with multiple  servers.
> 2. Delete database code in some of the missed test files.
> 3. Added advanced configurations in test_advanced_config.json.in for roles &
> tablespaces. So, accordingly you need change the file
> test_advanced_config.json
> 4. Added one test user credentials in test_config.json.in to test the ‘valid
> password’ test case which is present in
> browser/tests/test_change_password.py
>     Why test user credentials in test_config.json.in?
>            Currently, I am getting ‘UnicodeDecodeError’ when I run
> test-suite(runtests.py) with existing code. I already explained the detail
> about this error in RM(#1521). I am creating test user to test the ‘valid
> password’ test case.

The tablespace test is one that I think is going to cause us problems
- we really can't have a hard-coded path in the config;

- It might need to be different for each server being tested

- It is very likely to be different for each user

I think what we need to do is:

- Skip the tests if the server is not connected via a Unix domain
socket (hostname starts with /), 127.0.0.1 or ::1.

- Add per-server configuration options for the tablespace path and
service account under which the database server runs. These values
should default to /tmp and postgres for a PostgreSQL server, and edb
for PPAS.

- Otherwise; assume the server is on the local machine, and:
  - Create /$tblspace_path/<random_string>/
  - chown $service_account /$tblspace_path/<random_string>/
  - Run the tests

Thoughts?

I'd also suggest another couple of changes:

- Remove the test_ prefix from the values in the config files. It
doesn't really help in the code as there you'll always have the data
in a variable anyway, e.g. adv_config_data["spc_location"] instead of
adv_config_data["test_spc_location"].

- I think we should fall back to using test_advanced_config.json.in if
the user hasn't made their own copy, e.g.

try:
    with open(CURRENT_PATH + '/test_advanced_config.json') as data_file:
        advanced_config_data = json.load(data_file)
except:
    with open(CURRENT_PATH + '/test_advanced_config.json.in') as data_file:
        advanced_config_data = json.load(data_file)



-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-03 13:01  Navnath Gadakh <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-08-03 13:01 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,
     Thanks for clarification.

On Wed, Aug 3, 2016 at 2:45 PM, Dave Page <[email protected]>
wrote:

> Hi Navnath
>
> On Tue, Aug 2, 2016 at 3:58 PM, Navnath Gadakh
> <[email protected]> wrote:
> > Hi Dave,
> >      Please find the attached patch.
> > This patch includes:
> > 1. API test cases for Roles & Tablespaces node(Completed nodes: server
> > groups, servers, databases)
> >     You can run test-suite using following command
> >      for roles node
> >                python regression/runtests.py --pkg
> > browser.server_groups.servers.roles
> >      for tablespaces node
> >                python regression/runtests.py --pkg
> > browser.server_groups.servers.tablespaces
> >      for all nodes
> >                python regression/runtests.py
> >      You can also test with multiple  servers.
> > 2. Delete database code in some of the missed test files.
> > 3. Added advanced configurations in test_advanced_config.json.in for
> roles &
> > tablespaces. So, accordingly you need change the file
> > test_advanced_config.json
> > 4. Added one test user credentials in test_config.json.in to test the
> ‘valid
> > password’ test case which is present in
> > browser/tests/test_change_password.py
> >     Why test user credentials in test_config.json.in?
> >            Currently, I am getting ‘UnicodeDecodeError’ when I run
> > test-suite(runtests.py) with existing code. I already explained the
> detail
> > about this error in RM(#1521). I am creating test user to test the ‘valid
> > password’ test case.
>
> The tablespace test is one that I think is going to cause us problems
> - we really can't have a hard-coded path in the config;
>
      Understood.

>
> - It might need to be different for each server being tested
>   Current patch supports multiple servers if you add
> tablespace configurations for multiple servers. In the current patch, it's
> only for one server.
>
      For multiple servers you need to add multiple
tablespace configuration:
          "test_tablespc_credentials":[{
    "test_tblspace_name": "test_tablespace",
    "test_spc_location": "/Library/PostgreSQL/9.6/data",
    "test_spc_opts": [],
    "test_spc_user": "XXXXX"
  },
  "test_tblspace_name": "test_tablespace1",
    "test_spc_seclable": [],
    "test_spc_location": "/Library/PostgrePlus/9.4AS/data",
    "test_spc_opts": [],
    "test_spc_user": "YYYYY"
  }]
   Anyhow, we are not going to use a hard coded path.

- It is very likely to be different for each user
>
> I think what we need to do is:
>
> - Skip the tests if the server is not connected via a Unix domain
> socket (hostname starts with /), 127.0.0.1 or ::1.
>
    Understood.

>
> - Add per-server configuration options for the tablespace path and
> service account under which the database server runs. These values
> should default to /tmp and postgres for a PostgreSQL server, and edb
> for PPAS.
>
    Ok. For server connected via Unix domain socket. As per my
understanding modified configuration should be,
     "tablespc_credentials":[{
    "tblspace_name": "tablespace1",
    "testspc_seclable": [],
    "spc_acl": [
      {
        "grantee":"postgres",
        "grantor":"postgres",
        "privileges":[
          {
            "privilege_type":"C",
            "privilege":true,
            "with_grant":false
          }
        ]
      }
    ],
    "spc_location": "/tmp",
    "spc_opts": [],
    "spc_user": "postgres",
    "service_account": "test1_user"
  },{
    "tblspace_name": "tablespace2",
    "spc_seclable": [],
    "spc_acl": [
      {
        "grantee":"enterprisedb",
        "grantor":"enterprisedb",
        "privileges":[
          {
            "privilege_type":"C",
            "privilege":true,
            "with_grant":false
          }
        ]
      }
    ],
    "spc_location": "/tmp",
    "spc_opts": [],
    "spc_user": "enterprisedb",
    "service_account": "test2_user"
  }]
        Please correct me if I am wrong.

>
> - Otherwise; assume the server is on the local machine, and:
>   - Create /$tblspace_path/<random_string>/
>   - chown $service_account /$tblspace_path/<random_string>/
>   - Run the tests
>
      We can't set the owner for a tablespace path directory using normal
user, the user should be 'root'
      Say, I am logged in my machine as a 'abc' user  & I have installed
PostgreSQL9.5 with 'postgres' user.
      It won't run chown postgres /$tablespace_path_for_PostgreSQL9.5
/<random_string>

>
> Thoughts?
>
> I'd also suggest another couple of changes:
>
> - Remove the test_ prefix from the values in the config files. It
> doesn't really help in the code as there you'll always have the data
> in a variable anyway, e.g. adv_config_data["spc_location"] instead of
> adv_config_data["test_spc_location"].
>
> - I think we should fall back to using test_advanced_config.json.in if
> the user hasn't made their own copy, e.g.
>
> try:
>     with open(CURRENT_PATH + '/test_advanced_config.json') as data_file:
>         advanced_config_data = json.load(data_file)
> except:
>     with open(CURRENT_PATH + '/test_advanced_config.json.in') as
> data_file:
>         advanced_config_data = json.load(data_file)

    Understood.

>
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>



-- 
Thanks,
Navnath Gadakh
Software Engineer
EnterpriseDB Corporation
Mobile: +91 9975389878


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-03 15:02  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Dave Page @ 2016-08-03 15:02 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

On Wed, Aug 3, 2016 at 2:01 PM, Navnath Gadakh
<[email protected]> wrote:
> Hi Dave,
>      Thanks for clarification.
>
> On Wed, Aug 3, 2016 at 2:45 PM, Dave Page <[email protected]>
> wrote:
>>
>> Hi Navnath
>>
>> On Tue, Aug 2, 2016 at 3:58 PM, Navnath Gadakh
>> <[email protected]> wrote:
>> > Hi Dave,
>> >      Please find the attached patch.
>> > This patch includes:
>> > 1. API test cases for Roles & Tablespaces node(Completed nodes: server
>> > groups, servers, databases)
>> >     You can run test-suite using following command
>> >      for roles node
>> >                python regression/runtests.py --pkg
>> > browser.server_groups.servers.roles
>> >      for tablespaces node
>> >                python regression/runtests.py --pkg
>> > browser.server_groups.servers.tablespaces
>> >      for all nodes
>> >                python regression/runtests.py
>> >      You can also test with multiple  servers.
>> > 2. Delete database code in some of the missed test files.
>> > 3. Added advanced configurations in test_advanced_config.json.in for
>> > roles &
>> > tablespaces. So, accordingly you need change the file
>> > test_advanced_config.json
>> > 4. Added one test user credentials in test_config.json.in to test the
>> > ‘valid
>> > password’ test case which is present in
>> > browser/tests/test_change_password.py
>> >     Why test user credentials in test_config.json.in?
>> >            Currently, I am getting ‘UnicodeDecodeError’ when I run
>> > test-suite(runtests.py) with existing code. I already explained the
>> > detail
>> > about this error in RM(#1521). I am creating test user to test the
>> > ‘valid
>> > password’ test case.
>>
>> The tablespace test is one that I think is going to cause us problems
>> - we really can't have a hard-coded path in the config;
>
>       Understood.
>>
>>
>> - It might need to be different for each server being tested
>>   Current patch supports multiple servers if you add tablespace
>> configurations for multiple servers. In the current patch, it's only for one
>> server.
>
>       For multiple servers you need to add multiple tablespace
> configuration:
>           "test_tablespc_credentials":[{
>     "test_tblspace_name": "test_tablespace",
>     "test_spc_location": "/Library/PostgreSQL/9.6/data",
>     "test_spc_opts": [],
>     "test_spc_user": "XXXXX"
>   },
>   "test_tblspace_name": "test_tablespace1",
>     "test_spc_seclable": [],
>     "test_spc_location": "/Library/PostgrePlus/9.4AS/data",
>     "test_spc_opts": [],
>     "test_spc_user": "YYYYY"
>   }]
>    Anyhow, we are not going to use a hard coded path.

Oh - does the per-server config override the main config? That's
useful. So anything that's in test_advanced_config.py can be
overridden on a per-server basis in test_config.py?

>> - It is very likely to be different for each user
>>
>> I think what we need to do is:
>>
>> - Skip the tests if the server is not connected via a Unix domain
>> socket (hostname starts with /), 127.0.0.1 or ::1.
>
>     Understood.

Please output a notice saying the test was skipped, and note it in the
summary as well (as we're planning to do with failed tests).

>>
>> - Add per-server configuration options for the tablespace path and
>> service account under which the database server runs. These values
>> should default to /tmp and postgres for a PostgreSQL server, and edb
>> for PPAS.
>
>     Ok. For server connected via Unix domain socket. As per my understanding
> modified configuration should be,
>      "tablespc_credentials":[{
>     "tblspace_name": "tablespace1",
>     "testspc_seclable": [],
>     "spc_acl": [
>       {
>         "grantee":"postgres",
>         "grantor":"postgres",
>         "privileges":[
>           {
>             "privilege_type":"C",
>             "privilege":true,
>             "with_grant":false
>           }
>         ]
>       }
>     ],
>     "spc_location": "/tmp",
>     "spc_opts": [],
>     "spc_user": "postgres",
>     "service_account": "test1_user"
>   },{
>     "tblspace_name": "tablespace2",
>     "spc_seclable": [],
>     "spc_acl": [
>       {
>         "grantee":"enterprisedb",
>         "grantor":"enterprisedb",
>         "privileges":[
>           {
>             "privilege_type":"C",
>             "privilege":true,
>             "with_grant":false
>           }
>         ]
>       }
>     ],
>     "spc_location": "/tmp",
>     "spc_opts": [],
>     "spc_user": "enterprisedb",
>     "service_account": "test2_user"
>   }]
>         Please correct me if I am wrong.

Something like that yes - though service_account seems pointless given
your comment below...

>> - Otherwise; assume the server is on the local machine, and:
>>   - Create /$tblspace_path/<random_string>/
>>   - chown $service_account /$tblspace_path/<random_string>/
>>   - Run the tests
>
>       We can't set the owner for a tablespace path directory using normal
> user, the user should be 'root'
>       Say, I am logged in my machine as a 'abc' user  & I have installed
> PostgreSQL9.5 with 'postgres' user.
>       It won't run chown postgres
> /$tablespace_path_for_PostgreSQL9.5/<random_string>

Aww crap. Yeah :-(. OK in that case let's have the user specify (and
create) the path themselves for each server. If they don't specify a
path, then skip the test.

In fact - you might as well only skip the test in that case, and
forget about the address check above.

-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-04 09:27  Navnath Gadakh <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-08-04 09:27 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,

On Wed, Aug 3, 2016 at 8:32 PM, Dave Page <[email protected]>
wrote:

> On Wed, Aug 3, 2016 at 2:01 PM, Navnath Gadakh
> <[email protected]> wrote:
> > Hi Dave,
> >      Thanks for clarification.
> >
> > On Wed, Aug 3, 2016 at 2:45 PM, Dave Page <[email protected]>
> > wrote:
> >>
> >> Hi Navnath
> >>
> >> On Tue, Aug 2, 2016 at 3:58 PM, Navnath Gadakh
> >> <[email protected]> wrote:
> >> > Hi Dave,
> >> >      Please find the attached patch.
> >> > This patch includes:
> >> > 1. API test cases for Roles & Tablespaces node(Completed nodes: server
> >> > groups, servers, databases)
> >> >     You can run test-suite using following command
> >> >      for roles node
> >> >                python regression/runtests.py --pkg
> >> > browser.server_groups.servers.roles
> >> >      for tablespaces node
> >> >                python regression/runtests.py --pkg
> >> > browser.server_groups.servers.tablespaces
> >> >      for all nodes
> >> >                python regression/runtests.py
> >> >      You can also test with multiple  servers.
> >> > 2. Delete database code in some of the missed test files.
> >> > 3. Added advanced configurations in test_advanced_config.json.in for
> >> > roles &
> >> > tablespaces. So, accordingly you need change the file
> >> > test_advanced_config.json
> >> > 4. Added one test user credentials in test_config.json.in to test the
> >> > ‘valid
> >> > password’ test case which is present in
> >> > browser/tests/test_change_password.py
> >> >     Why test user credentials in test_config.json.in?
> >> >            Currently, I am getting ‘UnicodeDecodeError’ when I run
> >> > test-suite(runtests.py) with existing code. I already explained the
> >> > detail
> >> > about this error in RM(#1521). I am creating test user to test the
> >> > ‘valid
> >> > password’ test case.
> >>
> >> The tablespace test is one that I think is going to cause us problems
> >> - we really can't have a hard-coded path in the config;
> >
> >       Understood.
> >>
> >>
> >> - It might need to be different for each server being tested
> >>   Current patch supports multiple servers if you add tablespace
> >> configurations for multiple servers. In the current patch, it's only
> for one
> >> server.
> >
> >       For multiple servers you need to add multiple tablespace
> > configuration:
> >           "test_tablespc_credentials":[{
> >     "test_tblspace_name": "test_tablespace",
> >     "test_spc_location": "/Library/PostgreSQL/9.6/data",
> >     "test_spc_opts": [],
> >     "test_spc_user": "XXXXX"
> >   },
> >   "test_tblspace_name": "test_tablespace1",
> >     "test_spc_seclable": [],
> >     "test_spc_location": "/Library/PostgrePlus/9.4AS/data",
> >     "test_spc_opts": [],
> >     "test_spc_user": "YYYYY"
> >   }]
> >    Anyhow, we are not going to use a hard coded path.
>
> Oh - does the per-server config override the main config? That's
> useful. So anything that's in test_advanced_config.py can be
> overridden on a per-server basis in test_config.py?

    No.
    per-server i.e advance config(test_advanced_config.json.in) and main
config(test_config.json) both are different files. In main config we just
  mention the server’s credentials.(We can also mention per server
credentails) and in test_advanced_config.json.in(here we say per-server
config)
we mention the advanced configurations i.e. test data for each node.


>
> >> - It is very likely to be different for each user
> >>
> >> I think what we need to do is:
> >>
> >> - Skip the tests if the server is not connected via a Unix domain
> >> socket (hostname starts with /), 127.0.0.1 or ::1.
> >
> >     Understood.
>
> Please output a notice saying the test was skipped, and note it in the
> summary as well (as we're planning to do with failed tests).
>
> >>
> >> - Add per-server configuration options for the tablespace path and
> >> service account under which the database server runs. These values
> >> should default to /tmp and postgres for a PostgreSQL server, and edb
> >> for PPAS.
> >
> >     Ok. For server connected via Unix domain socket. As per my
> understanding
> > modified configuration should be,
> >      "tablespc_credentials":[{
> >     "tblspace_name": "tablespace1",
> >     "testspc_seclable": [],
> >     "spc_acl": [
> >       {
> >         "grantee":"postgres",
> >         "grantor":"postgres",
> >         "privileges":[
> >           {
> >             "privilege_type":"C",
> >             "privilege":true,
> >             "with_grant":false
> >           }
> >         ]
> >       }
> >     ],
> >     "spc_location": "/tmp",
> >     "spc_opts": [],
> >     "spc_user": "postgres",
> >     "service_account": "test1_user"
> >   },{
> >     "tblspace_name": "tablespace2",
> >     "spc_seclable": [],
> >     "spc_acl": [
> >       {
> >         "grantee":"enterprisedb",
> >         "grantor":"enterprisedb",
> >         "privileges":[
> >           {
> >             "privilege_type":"C",
> >             "privilege":true,
> >             "with_grant":false
> >           }
> >         ]
> >       }
> >     ],
> >     "spc_location": "/tmp",
> >     "spc_opts": [],
> >     "spc_user": "enterprisedb",
> >     "service_account": "test2_user"
> >   }]
> >         Please correct me if I am wrong.
>
> Something like that yes - though service_account seems pointless given
> your comment below...
>
> >> - Otherwise; assume the server is on the local machine, and:
> >>   - Create /$tblspace_path/<random_string>/
> >>   - chown $service_account /$tblspace_path/<random_string>/
> >>   - Run the tests
> >
> >       We can't set the owner for a tablespace path directory using normal
> > user, the user should be 'root'
> >       Say, I am logged in my machine as a 'abc' user  & I have installed
> > PostgreSQL9.5 with 'postgres' user.
> >       It won't run chown postgres
> > /$tablespace_path_for_PostgreSQL9.5/<random_string>
>
> Aww crap. Yeah :-(. OK in that case let's have the user specify (and
> create) the path themselves for each server. If they don't specify a
> path, then skip the test.
>
> In fact - you might as well only skip the test in that case, and
> forget about the address check above.
>
>     So, let's summarize the discussion:
    - Let user specify the tablespace path in test_advanced_config.json.in
    - If path not specified in the test_advanced_config.json.in skip the
test cases for tablespace.
    - Output a notice saying the test was skipped, and note it in the
summary.
    - No need to check the address.(Unix domain socket). It seems correct
way.

   Please tell me if I missed anything.

   Thanks!

--
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>



-- 
Thanks,
Navnath Gadakh
Software Engineer
EnterpriseDB Corporation
Mobile: +91 9975389878


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-04 10:34  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Dave Page @ 2016-08-04 10:34 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi

On Thu, Aug 4, 2016 at 10:27 AM, Navnath Gadakh
<[email protected]> wrote:

>> Oh - does the per-server config override the main config? That's
>> useful. So anything that's in test_advanced_config.py can be
>> overridden on a per-server basis in test_config.py?
>
>     No.
>     per-server i.e advance config(test_advanced_config.json.in) and main
> config(test_config.json) both are different files. In main config we just
> mention the server’s credentials.(We can also mention per server
> credentails) and in test_advanced_config.json.in(here we say per-server
> config)
> we mention the advanced configurations i.e. test data for each node.

OK.

>     So, let's summarize the discussion:
>     - Let user specify the tablespace path in test_advanced_config.json.in

No - test_config.py. It should be per-server.

>     - If path not specified in the test_advanced_config.json.in skip the
> test cases for tablespace.

Yes (but, test_config.py), for that server only.

>     - Output a notice saying the test was skipped, and note it in the
> summary.

Yes.

>     - No need to check the address.(Unix domain socket). It seems correct
> way.

Right.

Thanks!

-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-04 12:02  Navnath Gadakh <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-08-04 12:02 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,

On Thu, Aug 4, 2016 at 4:04 PM, Dave Page <[email protected]>
wrote:

> Hi
>
> On Thu, Aug 4, 2016 at 10:27 AM, Navnath Gadakh
> <[email protected]> wrote:
>
> >> Oh - does the per-server config override the main config? That's
> >> useful. So anything that's in test_advanced_config.py can be
> >> overridden on a per-server basis in test_config.py?
> >
> >     No.
> >     per-server i.e advance config(test_advanced_config.json.in) and main
> > config(test_config.json) both are different files. In main config we just
> > mention the server’s credentials.(We can also mention per server
> > credentails) and in test_advanced_config.json.in(here we say per-server
> > config)
> > we mention the advanced configurations i.e. test data for each node.
>
> OK.
>
> >     So, let's summarize the discussion:
> >     - Let user specify the tablespace path in
> test_advanced_config.json.in
>
> No - test_config.py. It should be per-server.
>
     We don't have a file named 'test_config.py' but we have a server's
credential file named 'test_config.json'.
     So, you are saying the tablespace path to be added in
'test_config.json'.
     Am I correct?


>
> >     - If path not specified in the test_advanced_config.json.in skip the
> > test cases for tablespace.
>
> Yes (but, test_config.py), for that server only.
>
> >     - Output a notice saying the test was skipped, and note it in the
> > summary.
>
> Yes.
>
> >     - No need to check the address.(Unix domain socket). It seems correct
> > way.
>
> Right.
>
> Thanks!
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>



-- 
Thanks,
Navnath Gadakh
Software Engineer
EnterpriseDB Corporation
Mobile: +91 9975389878


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-04 12:25  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Dave Page @ 2016-08-04 12:25 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

On Thu, Aug 4, 2016 at 1:02 PM, Navnath Gadakh
<[email protected]> wrote:
> Hi Dave,
>
> On Thu, Aug 4, 2016 at 4:04 PM, Dave Page <[email protected]>
> wrote:
>>
>> Hi
>>
>> On Thu, Aug 4, 2016 at 10:27 AM, Navnath Gadakh
>> <[email protected]> wrote:
>>
>> >> Oh - does the per-server config override the main config? That's
>> >> useful. So anything that's in test_advanced_config.py can be
>> >> overridden on a per-server basis in test_config.py?
>> >
>> >     No.
>> >     per-server i.e advance config(test_advanced_config.json.in) and main
>> > config(test_config.json) both are different files. In main config we
>> > just
>> > mention the server’s credentials.(We can also mention per server
>> > credentails) and in test_advanced_config.json.in(here we say per-server
>> > config)
>> > we mention the advanced configurations i.e. test data for each node.
>>
>> OK.
>>
>> >     So, let's summarize the discussion:
>> >     - Let user specify the tablespace path in
>> > test_advanced_config.json.in
>>
>> No - test_config.py. It should be per-server.
>
>      We don't have a file named 'test_config.py' but we have a server's
> credential file named 'test_config.json'.
>      So, you are saying the tablespace path to be added in
> 'test_config.json'.
>      Am I correct?

Yeah, sorry. It should be a property of the server configuration.


-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-08 14:07  Navnath Gadakh <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-08-08 14:07 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,
    Please find the updated patch for API unit test cases for *Roles and
Tablespaces *nodes
As we finalized
Now,
   1. The user will specify the tablespace path in test_config.json.in
   2.  If tablespace path not found, skip the test cases for that
server(Only tablespace test cases)
   3.  Add the skipped test summary in the test result. (Now it's
showing on console + in log file, but need to update in a final enhanced
test summary report. Which is research point we will work on that after
finishing all nodes API test cases)
   4.  Removed the test_ prefix from the values in the config files.

Thanks!


On Thu, Aug 4, 2016 at 5:55 PM, Dave Page <[email protected]>
wrote:

> On Thu, Aug 4, 2016 at 1:02 PM, Navnath Gadakh
> <[email protected]> wrote:
> > Hi Dave,
> >
> > On Thu, Aug 4, 2016 at 4:04 PM, Dave Page <[email protected]>
> > wrote:
> >>
> >> Hi
> >>
> >> On Thu, Aug 4, 2016 at 10:27 AM, Navnath Gadakh
> >> <[email protected]> wrote:
> >>
> >> >> Oh - does the per-server config override the main config? That's
> >> >> useful. So anything that's in test_advanced_config.py can be
> >> >> overridden on a per-server basis in test_config.py?
> >> >
> >> >     No.
> >> >     per-server i.e advance config(test_advanced_config.json.in) and
> main
> >> > config(test_config.json) both are different files. In main config we
> >> > just
> >> > mention the server’s credentials.(We can also mention per server
> >> > credentails) and in test_advanced_config.json.in(here we say
> per-server
> >> > config)
> >> > we mention the advanced configurations i.e. test data for each node.
> >>
> >> OK.
> >>
> >> >     So, let's summarize the discussion:
> >> >     - Let user specify the tablespace path in
> >> > test_advanced_config.json.in
> >>
> >> No - test_config.py. It should be per-server.
> >
> >      We don't have a file named 'test_config.py' but we have a server's
> > credential file named 'test_config.json'.
> >      So, you are saying the tablespace path to be added in
> > 'test_config.json'.
> >      Am I correct?
>
> Yeah, sorry. It should be a property of the server configuration.
>
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>



-- 
Thanks,
Navnath Gadakh
Software Engineer
EnterpriseDB Corporation
Mobile: +91 9975389878


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [application/octet-stream] pgadmin_unittest_roles_tablespaces.patch (104.9K, 3-pgadmin_unittest_roles_tablespaces.patch)
  download | inline diff:
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
index 85dcc6c..490e7d9 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
@@ -7,10 +7,11 @@
 #
 # ##################################################################
 
-import json
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as database_utils
 
 
 class DatabaseAddTestCase(BaseTestGenerator):
@@ -24,7 +25,8 @@ class DatabaseAddTestCase(BaseTestGenerator):
         ('Check Databases Node URL', dict(url='/browser/database/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function used to add the sever
 
@@ -32,27 +34,23 @@ class DatabaseAddTestCase(BaseTestGenerator):
         """
 
         # Add the server
-        utils.add_server(self.tester)
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the database!!!")
 
     def runTest(self):
         """ This function will add database under 1st server of tree node. """
 
-        server_connect_response, server_group, server_ids = \
-            utils.connect_server(self.tester)
-
-        for server_connect, server_id in zip(server_connect_response,
-                                             server_ids):
-            if server_connect['data']['connected']:
-                data = utils.get_db_data(server_connect)
-                db_response = self.tester.post(self.url + str(server_group) +
-                                               "/" + server_id + "/",
-                                               data=json.dumps(data),
-                                               content_type='html/json')
-                self.assertTrue(db_response.status_code, 200)
-                response_data = json.loads(db_response.data.decode('utf-8'))
-                utils.write_db_parent_id(response_data)
+        database_utils.add_database(self.tester, self.server_connect_response,
+                                    self.server_ids)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the added database, added server and the
         'parent_id.pkl' file which is created in setup()
@@ -60,6 +58,6 @@ class DatabaseAddTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_database(self.tester)
-        utils.delete_server(self.tester)
+        database_utils.delete_database(cls.tester)
+        server_utils.delete_server(cls.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
index 6830b5a..756a689 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
@@ -7,12 +7,10 @@
 #
 # ##################################################################
 
-import json
-
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import config_data
-from regression.test_utils import get_ids
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as database_utils
 
 
 class DatabaseDeleteTestCase(BaseTestGenerator):
@@ -23,43 +21,38 @@ class DatabaseDeleteTestCase(BaseTestGenerator):
         ('Check Databases Node URL', dict(url='/browser/database/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function perform the three tasks
          1. Add the test server
          2. Connect to server
+         3. Add the databases
 
         :return: None
         """
 
         # Firstly, add the server
-        utils.add_server(self.tester)
-        # Secondly, connect to server/database
-        utils.connect_server(self.tester)
+        server_utils.add_server(cls.tester)
 
-    def runTest(self):
-        """ This function will delete the database."""
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
 
-        srv_grp = config_data['test_server_group']
-        all_id = get_ids()
-        server_ids = all_id["sid"]
-        db_ids_dict = all_id["did"][0]
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the database!!!")
 
-        for server_id in server_ids:
-            db_id = db_ids_dict[int(server_id)]
-            db_con = utils.verify_database(self.tester, srv_grp, server_id,
-                                           db_id)
-            if len(db_con) == 0:
-                raise Exception("No database(s) to delete for server id %s"
-                                % server_id)
-            response = self.tester.delete(self.url + str(srv_grp) + '/' +
-                                          str(server_id) + '/' + str(db_id),
-                                          follow_redirects=True)
+        # Add database
+        database_utils.add_database(cls.tester, cls.server_connect_response,
+                                    cls.server_ids)
+
+    def runTest(self):
+        """ This function will delete the database."""
 
-            response_data = json.loads(response.data.decode('utf-8'))
-            self.assertTrue(response_data['success'], 1)
+        database_utils.delete_database(self.tester)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the added server and the 'parent_id.pkl' file
         which is created in setup() function.
@@ -67,5 +60,5 @@ class DatabaseDeleteTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_server(self.tester)
+        server_utils.delete_server(cls.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
index 7350f72..739dff8 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
@@ -11,6 +11,8 @@ from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
 from regression.test_setup import config_data
 from regression.test_utils import get_ids
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as database_utils
 
 
 class DatabasesGetTestCase(BaseTestGenerator):
@@ -20,22 +22,33 @@ class DatabasesGetTestCase(BaseTestGenerator):
 
     scenarios = [
         # Fetching default URL for database node.
-        ('Check Databases Node URL', dict(url='/browser/database/obj/'))
+        ('Check Dat abases Node URL', dict(url='/browser/database/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function perform the three tasks
          1. Add the test server
          2. Connect to server
+         3. Add the databases
 
         :return: None
         """
 
         # Firstly, add the server
-        utils.add_server(self.tester)
-        # Secondly, connect to server/database
-        utils.connect_server(self.tester)
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the database!!!")
+
+        # Add database
+        database_utils.add_database(cls.tester, cls.server_connect_response,
+                                    cls.server_ids)
 
     def runTest(self):
         """ This function will fetch added database. """
@@ -44,19 +57,21 @@ class DatabasesGetTestCase(BaseTestGenerator):
         server_ids = all_id["sid"]
 
         db_ids_dict = all_id["did"][0]
-        srv_grp = config_data['test_server_group']
+        srv_grp = config_data['server_group']
 
         for server_id in server_ids:
             db_id = db_ids_dict[int(server_id)]
-            db_con = utils.verify_database(self.tester, srv_grp, server_id,
-                                           db_id)
+            db_con = database_utils.verify_database(self.tester, srv_grp,
+                                                    server_id,
+                                                    db_id)
             if db_con["info"] == "Database connected.":
                 response = self.tester.get(
                     self.url + str(srv_grp) + '/' + str(server_id) + '/' +
                     str(db_id), follow_redirects=True)
                 self.assertEquals(response.status_code, 200)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the added database, added server
         and the 'parent_id.pkl' file which is created in setup() function.
@@ -64,6 +79,6 @@ class DatabasesGetTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_database(self.tester)
-        utils.delete_server(self.tester)
+        database_utils.delete_database(cls.tester)
+        server_utils.delete_server(cls.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
index 4615d34..c32e3ca 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
@@ -11,8 +11,10 @@ import json
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import config_data, advanced_config_data
+from regression.test_setup import advanced_config_data
 from regression.test_utils import get_ids
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as database_utils
 
 
 class DatabasesUpdateTestCase(BaseTestGenerator):
@@ -25,44 +27,58 @@ class DatabasesUpdateTestCase(BaseTestGenerator):
         ('Check Databases Node', dict(url='/browser/database/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function perform the three tasks
          1. Add the test server
          2. Connect to server
+         3. Add the databases
 
         :return: None
         """
 
         # Firstly, add the server
-        utils.add_server(self.tester)
-        # Secondly, connect to server/database
-        utils.connect_server(self.tester)
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the database!!!")
+
+        # Add database
+        database_utils.add_database(cls.tester, cls.server_connect_response,
+                                    cls.server_ids)
 
     def runTest(self):
         """ This function will update the comments field of database."""
 
-        srv_grp = config_data['test_server_group']
         all_id = get_ids()
         server_ids = all_id["sid"]
         db_ids_dict = all_id["did"][0]
 
         for server_id in server_ids:
             db_id = db_ids_dict[int(server_id)]
-            db_con = utils.verify_database(self.tester, srv_grp, server_id,
-                                           db_id)
+            db_con = database_utils.verify_database(self.tester,
+                                                    utils.SERVER_GROUP,
+                                                    server_id,
+                                                    db_id)
             if db_con["info"] == "Database connected.":
                 data = {
-                    "comments": advanced_config_data["test_db_update_data"][0]
-                    ["test_comment"],
+                    "comments": advanced_config_data["db_update_data"][0]
+                    ["comment"],
                     "id": db_id
                 }
                 put_response = self.tester.put(
-                    self.url + str(srv_grp) + '/' + str(server_id) + '/' +
+                    self.url + str(utils.SERVER_GROUP) + '/' + str(
+                        server_id) + '/' +
                     str(db_id), data=json.dumps(data), follow_redirects=True)
                 self.assertEquals(put_response.status_code, 200)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(self):
         """
         This function deletes the added server and 'parent_id.pkl' file
         which is created in setup() function.
@@ -70,5 +86,6 @@ class DatabasesUpdateTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_server(self.tester)
+        database_utils.delete_database(self.tester)
+        server_utils.delete_server(self.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/utils.py b/web/pgadmin/browser/server_groups/servers/databases/tests/utils.py
new file mode 100644
index 0000000..fcffaf4
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/utils.py
@@ -0,0 +1,176 @@
+# ##########################################################################
+#
+# #pgAdmin 4 - PostgreSQL Tools
+#
+# #Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# #This software is released under the PostgreSQL Licence
+#
+# ##########################################################################
+
+import json
+import os
+import pickle
+import uuid
+
+from regression.test_setup import pickle_path, config_data, advanced_config_data
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from regression import test_utils as utils
+
+
+DATABASE_URL = '/browser/database/obj/'
+DATABASE_CONNECT_URL = 'browser/database/connect/'
+
+
+def get_db_data(server_connect_data):
+    """
+    This function is used to get advance config test data for appropriate
+    server
+
+    :param server_connect_data: list of server details
+    :return data: database details
+    :rtype: dict
+    """
+
+    adv_config_data = None
+    data = None
+    db_user = server_connect_data['data']['user']['name']
+
+    # Get the config data of appropriate db user
+    for config_test_data in advanced_config_data['add_database_data']:
+        if db_user == config_test_data['owner']:
+            adv_config_data = config_test_data
+
+    if adv_config_data is not None:
+        data = {
+            "datacl": adv_config_data['privileges_acl'],
+            "datconnlimit": adv_config_data['conn_limit'],
+            "datowner": adv_config_data['owner'],
+            "deffuncacl": adv_config_data['fun_acl'],
+            "defseqacl": adv_config_data['seq_acl'],
+            "deftblacl": adv_config_data['tbl_acl'],
+            "deftypeacl": adv_config_data['type_acl'],
+            "encoding": adv_config_data['encoding'],
+            "name": str(uuid.uuid4())[1:8],
+            "privileges": adv_config_data['privileges'],
+            "securities": adv_config_data['securities'],
+            "variables": adv_config_data['variables']
+        }
+    return data
+
+
+def write_db_id(response_data):
+    """
+    This function writes the server and database related data like server
+    name, server id , database name, database id etc.
+
+    :param response_data: server and databases details
+    :type response_data: dict
+    :return: None
+    """
+
+    db_id = response_data['node']['_id']
+    server_id = response_data['node']['_pid']
+    pickle_id_dict = utils.get_pickle_id_dict()
+    if os.path.isfile(pickle_path):
+        existing_server_id = open(pickle_path, 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+    if 'did' in pickle_id_dict:
+        if pickle_id_dict['did']:
+            # Add the db_id as value in dict
+            pickle_id_dict["did"][0].update({server_id: db_id})
+        else:
+            # Create new dict with server_id and db_id
+            pickle_id_dict["did"].append({server_id: db_id})
+    db_output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, db_output)
+    db_output.close()
+
+
+def add_database(tester, server_connect_response, server_ids):
+    """
+    This function add the database into servers
+
+    :param tester: flask test client
+    :type tester: flask test object
+    :param server_connect_response: server response
+    :type server_connect_response: dict
+    :param server_ids: server ids
+    :type server_ids: list
+    :return: None
+    """
+
+    for server_connect, server_id in zip(server_connect_response, server_ids):
+        if server_connect['data']['connected']:
+            data = get_db_data(server_connect)
+            db_response = tester.post(DATABASE_URL + str(utils.SERVER_GROUP) +
+                                           "/" + server_id + "/",
+                                           data=json.dumps(data),
+                                           content_type='html/json')
+            assert db_response.status_code == 200
+            response_data = json.loads(db_response.data.decode('utf-8'))
+            write_db_id(response_data)
+
+
+def verify_database(tester, server_group, server_id, db_id):
+    """
+    This function verifies that database is exists and whether it connect
+    successfully or not
+
+    :param tester: test client
+    :type tester: flask test client object
+    :param server_group: server group id
+    :type server_group: int
+    :param server_id: server id
+    :type server_id: str
+    :param db_id: database id
+    :type db_id: str
+    :return: temp_db_con
+    :rtype: list
+    """
+
+    # Verify servers
+    server_utils.verify_server(tester,server_group,server_id)
+
+    # Connect to database
+    con_response = tester.post('{0}{1}/{2}/{3}'.format(
+        DATABASE_CONNECT_URL, server_group, server_id, db_id),
+        follow_redirects=True)
+    temp_db_con = json.loads(con_response.data.decode('utf-8'))
+
+    return temp_db_con
+
+
+def delete_database(tester):
+    """
+    This function used to delete the added databases
+
+    :param tester: test client object
+    :return: None
+    """
+
+    server_ids = None
+    db_ids_dict = None
+
+    all_id = utils.get_ids()
+    if "sid" and "did" in all_id.keys():
+        server_ids = all_id["sid"]
+        if all_id['did']:
+            db_ids_dict = all_id['did'][0]
+    else:
+        raise Exception("Keys are not found in pickle dict: {}".format(["sid", "did"]))
+
+    if server_ids and db_ids_dict is not None:
+        for server_id in server_ids:
+            server_response = server_utils.verify_server(tester, utils.SERVER_GROUP, server_id)
+            if server_response["data"]["connected"]:
+                db_id = db_ids_dict[int(server_id)]
+                response = tester.delete(DATABASE_URL + str(utils.SERVER_GROUP) + '/' +
+                                         str(server_id) + '/' + str(db_id),
+                                         follow_redirects=True)
+                assert response.status_code == 200
+                response_data = json.loads(response.data.decode('utf-8'))
+                assert response_data['success'] == 1
+    else:
+        raise Exception("No servers/databases found.")
+
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/roles/tests/__init__.py
new file mode 100644
index 0000000..4a11bf8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/__init__.py
@@ -0,0 +1,16 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class RoleGeneratorTestCase(BaseTestGenerator):
+
+    def runTest(self):
+        return
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_add.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_add.py
new file mode 100644
index 0000000..9d8f949
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_add.py
@@ -0,0 +1,55 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as roles_utils
+
+
+class LoginRoleAddTestCase(BaseTestGenerator):
+    """This class has add role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the roles!!!")
+
+    def runTest(self):
+        """This function test the add role scenario"""
+
+        roles_utils.add_role(self.tester, self.server_connect_response,
+                             self.server_group, self.server_ids)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the role,server and parent id file"""
+
+        roles_utils.delete_role(cls.tester)
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
+
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_delete.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_delete.py
new file mode 100644
index 0000000..f3204cd
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_delete.py
@@ -0,0 +1,58 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as roles_utils
+
+
+class LoginRoleDeleteTestCase(BaseTestGenerator):
+    """This class has delete role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever and roles
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the roles!!!")
+
+        # Add the role
+        roles_utils.add_role(cls.tester, cls.server_connect_response,
+                             cls.server_group, cls.server_ids)
+
+    def runTest(self):
+        """This function tests the delete role scenario"""
+
+        roles_utils.delete_role(self.tester)
+
+    @classmethod
+    def tearDownClass(self):
+        """This function deletes the role,server and parent id file"""
+
+        server_utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_get.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_get.py
new file mode 100644
index 0000000..4187fca
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_get.py
@@ -0,0 +1,67 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as roles_utils
+
+
+class LoginRoleGetTestCase(BaseTestGenerator):
+    """This class tests the get role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever and roles
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to get the roles!!!")
+
+        # Add the role
+        roles_utils.add_role(cls.tester, cls.server_connect_response,
+                             cls.server_group, cls.server_ids)
+
+    def runTest(self):
+        """This function test the get role scenario"""
+
+        all_id = utils.get_ids()
+        server_ids = all_id["sid"]
+        role_ids_dict = all_id["lrid"][0]
+
+        for server_id in server_ids:
+            role_id = role_ids_dict[int(server_id)]
+            response = self.tester.get(
+                self.url + str(utils.SERVER_GROUP) + '/' +
+                str(server_id) + '/' + str(role_id),
+                follow_redirects=True)
+            self.assertEquals(response.status_code, 200)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the role,server and parent id file"""
+
+        roles_utils.delete_role(cls.tester)
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_put.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_put.py
new file mode 100644
index 0000000..f8c353e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_put.py
@@ -0,0 +1,84 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from regression.test_setup import advanced_config_data
+from . import utils as roles_utils
+
+
+class LoginRolePutTestCase(BaseTestGenerator):
+    """This class has update role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever and roles
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to get the roles!!!")
+
+        # Add the role
+        roles_utils.add_role(cls.tester, cls.server_connect_response,
+                             cls.server_group, cls.server_ids)
+
+    def runTest(self):
+        """This function tests the update role data scenario"""
+
+        all_id = utils.get_ids()
+        server_ids = all_id["sid"]
+        role_ids_dict = all_id["lrid"][0]
+
+        for server_id in server_ids:
+            role_id = role_ids_dict[int(server_id)]
+            role_response = roles_utils.verify_role(self.tester,
+                                                    utils.SERVER_GROUP,
+                                                    server_id,
+                                                    role_id)
+            if len(role_response) == 0:
+                raise Exception("No roles(s) to update!!!")
+
+            data = {
+                "description": advanced_config_data["lr_update_data"]
+                ["comment"],
+                "lrid": role_id
+            }
+            put_response = self.tester.put(
+                self.url + str(utils.SERVER_GROUP) + '/' +
+                str(server_id) + '/' + str(role_id),
+                data=json.dumps(data),
+                follow_redirects=True)
+
+            self.assertEquals(put_response.status_code, 200)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the role,server and parent id file"""
+
+        roles_utils.delete_role(cls.tester)
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/utils.py b/web/pgadmin/browser/server_groups/servers/roles/tests/utils.py
new file mode 100644
index 0000000..85e0990
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/utils.py
@@ -0,0 +1,187 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+import os
+import pickle
+import uuid
+
+from regression.test_setup import pickle_path, config_data, advanced_config_data
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from regression import test_utils as utils
+
+
+ROLE_URL = '/browser/role/obj/'
+
+
+def verify_role(tester, server_group, server_id, role_id):
+    """
+    This function calls the GET API for role to verify
+
+    :param tester: test client
+    :type tester: flask test client object
+    :param server_group: server group id
+    :type server_group: int
+    :param server_id: server id
+    :type server_id: str
+    :param role_id: role id
+    :type role_id: int
+    :return: dict/None
+    """
+
+    srv_connect = server_utils.verify_server(tester, server_group, server_id)
+    if srv_connect['data']['connected']:
+        response = tester.get(
+            '{0}{1}/{2}/{3}'.format(ROLE_URL, server_group, server_id,
+                                    role_id),
+            content_type='html/json')
+        temp_response = json.loads(response.data.decode('utf-8'))
+        return temp_response
+    else:
+        return None
+
+
+def test_getrole(tester):
+    if not tester:
+        return None
+
+    all_id = utils.get_ids()
+
+    server_ids = all_id["sid"]
+    role_ids_dict = all_id["lrid"][0]
+    server_group = config_data['server_group']
+
+    role_response_data = []
+    for server_id in server_ids:
+        role_id = role_ids_dict[int(server_id)]
+        role_response_data.append(
+            verify_role(tester, server_group, server_id, role_id))
+    return role_response_data
+
+
+def get_role_data():
+    """This function returns the role data from config file"""
+
+    data = {
+        "rolcanlogin": advanced_config_data['lr_credentials']
+        ['can_login'],
+        "rolconnlimit": advanced_config_data['lr_credentials']
+        ['conn_limit'],
+        "rolcreaterole": advanced_config_data['lr_credentials']
+        ['create_role'],
+        "rolinherit": advanced_config_data['lr_credentials']
+        ['role_inherit'],
+        "rolmembership": advanced_config_data['lr_credentials']
+        ['role_membership'],
+        "rolname": str(uuid.uuid4())[1:8],
+        "rolpassword": advanced_config_data['lr_credentials']
+        ['lr_password'],
+        "rolvaliduntil": advanced_config_data['lr_credentials']
+        ['lr_validity'],
+        "seclabels": advanced_config_data['lr_credentials']
+        ['sec_lable'],
+        "variables": advanced_config_data['lr_credentials']
+        ['variable']
+    }
+    return data
+
+
+def add_role(tester, server_connect_response, server_group, server_ids):
+    """
+    This function is used to add the roles to server
+
+    :param tester: flask test client
+    :type tester: flask test client object
+    :param server_connect_response: server connect API response
+    :type server_connect_response: dict
+    :param server_group: server group
+    :type server_group: int
+    :param server_ids: list of server id
+    :type server_ids: list
+    :return: None
+    """
+
+    for server_connect, server_id in zip(server_connect_response,
+                                         server_ids):
+        if server_connect['data']['connected']:
+            data = get_role_data()
+            response = tester.post(ROLE_URL + str(server_group) + '/'
+                                   + server_id + '/', data=json.dumps(data),
+                                   content_type='html/json')
+            assert response.status_code == 200
+            response_data = json.loads(response.data.decode('utf-8'))
+            write_role_id(response_data)
+
+
+def write_role_id(response_data):
+    """
+
+    :param response_data:
+    :return:
+    """
+
+    lr_id = response_data['node']['_id']
+    server_id = response_data['node']['_pid']
+    pickle_id_dict = utils.get_pickle_id_dict()
+    # TODO: modify logic to write in file / file exists or create new check
+    # old file
+    if os.path.isfile(pickle_path):
+        existing_server_id = open(pickle_path, 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+    if 'lrid' in pickle_id_dict:
+        if pickle_id_dict['lrid']:
+            # Add the db_id as value in dict
+            pickle_id_dict["lrid"][0].update({server_id: lr_id})
+        else:
+            # Create new dict with server_id and db_id
+            pickle_id_dict["lrid"].append({server_id: lr_id})
+    db_output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, db_output)
+    db_output.close()
+
+
+def delete_role(tester):
+    """
+    This function use to delete the existing roles in the servers
+
+    :param tester: flask test client
+    :type tester: flask test object
+    :return: None
+    """
+
+    server_ids = None
+    role_ids_dict = None
+
+    all_id = utils.get_ids()
+    if "sid" and "lrid" in all_id.keys():
+        server_ids = all_id["sid"]
+        if all_id['lrid']:
+            role_ids_dict = all_id['lrid'][0]
+    else:
+        raise Exception("Keys are not found: {}".format(["sid", "lrid"]))
+
+    if server_ids and role_ids_dict is not None:
+        for server_id in server_ids:
+            server_response = server_utils.verify_server(tester,
+                                                         utils.SERVER_GROUP,
+                                                         server_id)
+            if server_response["data"]["connected"]:
+                role_id = role_ids_dict[int(server_id)]
+                response = tester.delete(
+                    ROLE_URL + str(utils.SERVER_GROUP) + '/' +
+                    str(server_id) + '/' + str(role_id),
+                    follow_redirects=True)
+                assert response.status_code == 200
+                response_data = json.loads(response.data.decode('utf-8'))
+                assert response_data['success'] == 1
+    else:
+        raise Exception("No servers/roles found.")
+
+
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/__init__.py
new file mode 100644
index 0000000..3302027
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/__init__.py
@@ -0,0 +1,16 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class TblspaceGeneratorTestCase(BaseTestGenerator):
+
+    def runTest(self):
+        return
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py
new file mode 100644
index 0000000..caa6966
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py
@@ -0,0 +1,55 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as tablespace_utils
+
+
+class TableSpaceAddTestCase(BaseTestGenerator):
+    """This class will add tablespace node under server"""
+
+    scenarios = [
+        # Fetching default URL for tablespace node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the roles!!!")
+
+    def runTest(self):
+        """This function test the add tablespace scenario"""
+
+        tablespace_status = tablespace_utils.add_table_space(
+            self.tester, self.server_connect_response, self.server_group,
+            self.server_ids)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the tablespaces,server and parent_id file"""
+
+        tablespace_utils.delete_table_space(cls.tester)
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py
new file mode 100644
index 0000000..f280ee6
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py
@@ -0,0 +1,58 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as tablespace_utils
+
+
+class TableSpaceDeleteTestCase(BaseTestGenerator):
+    """This class has delete table space scenario"""
+
+    scenarios = [
+        # Fetching default URL for tablespace node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the roles!!!")
+
+        # Add tablespace
+        tablespace_utils.add_table_space(cls.tester,
+                                         cls.server_connect_response,
+                                         cls.server_group, cls.server_ids)
+
+    def runTest(self):
+        """This function tests the delete table space scenario"""
+
+        tablespace_utils.delete_table_space(self.tester)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the server and parent id file"""
+
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py
new file mode 100644
index 0000000..b26d71d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py
@@ -0,0 +1,78 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as tablespace_utils
+
+
+class TablespaceGetTestCase(BaseTestGenerator):
+    """This class tests the get table space scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the roles!!!")
+
+        # Add tablespace
+        tablespace_utils.add_table_space(cls.tester,
+                                         cls.server_connect_response,
+                                         cls.server_group, cls.server_ids)
+
+    def runTest(self):
+        """This function test the get table space scenario"""
+
+        tablespace_ids_dict = None
+        all_id = utils.get_ids()
+        server_ids = all_id["sid"]
+        if "tsid" in all_id and all_id["tsid"]:
+            tablespace_ids_dict = all_id["tsid"][0]
+
+        if tablespace_ids_dict:
+            for server_id in server_ids:
+                tablespace_id = tablespace_ids_dict[int(server_id)]
+                server_response = server_utils.verify_server(self.tester,
+                                                             utils.SERVER_GROUP,
+                                                             server_id)
+                if server_response['data']['connected']:
+                    tablespace_utils.verify_table_space(
+                        self.tester, utils.SERVER_GROUP, server_id, tablespace_id)
+                    response = self.tester.get(
+                        self.url + str(utils.SERVER_GROUP) + '/' +
+                        str(server_id) + '/' + str(
+                            tablespace_id),
+                        follow_redirects=True)
+                    self.assertEquals(response.status_code, 200)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the tablespaces,server and parent id file"""
+
+        tablespace_utils.delete_table_space(cls.tester)
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py
new file mode 100644
index 0000000..22257f9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py
@@ -0,0 +1,90 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from test_setup import advanced_config_data
+from . import utils as tablespace_utils
+
+
+class TableSpaceUpdateTestCase(BaseTestGenerator):
+    """This class has update tablespace scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the roles!!!")
+
+        # Add tablespace
+        tablespace_utils.add_table_space(cls.tester,
+                                         cls.server_connect_response,
+                                         cls.server_group, cls.server_ids)
+
+    def runTest(self):
+        """This function tests the update tablespace data scenario"""
+
+        tablespace_ids_dict = None
+        all_id = utils.get_ids()
+        server_ids = all_id["sid"]
+        if "tsid" in all_id and all_id["tsid"]:
+            tablespace_ids_dict = all_id["tsid"][0]
+
+        if tablespace_ids_dict:
+            for server_id in server_ids:
+                tablespace_id = tablespace_ids_dict[int(server_id)]
+                tablespace_response = tablespace_utils.verify_table_space(
+                    self.tester,
+                    utils.SERVER_GROUP, server_id,
+                    tablespace_id)
+                if len(tablespace_response) == 0:
+                    raise Exception("No tablespace(s) to update!!!")
+
+                data = {
+                    "description": advanced_config_data["tbspc_update_data"]
+                    ["comment"],
+                    "table_space_id": tablespace_id
+                }
+
+                put_response = self.tester.put(
+                    self.url + str(utils.SERVER_GROUP) + '/' +
+                    str(server_id) + '/' + str(
+                        tablespace_id),
+                    data=json.dumps(data),
+                    follow_redirects=True)
+
+                self.assertEquals(put_response.status_code, 200)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the tablespaces,server and parent id file"""
+
+        tablespace_utils.delete_table_space(cls.tester)
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py
new file mode 100644
index 0000000..6943842
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py
@@ -0,0 +1,190 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from __future__ import print_function
+
+import json
+import os
+import pickle
+import uuid
+import sys
+
+from regression.test_setup import pickle_path, config_data, \
+    advanced_config_data
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from regression import test_utils as utils
+
+TABLE_SPACE_URL = '/browser/tablespace/obj/'
+
+
+# Tablespace utility
+def get_tablespace_data(server_connect):
+    """This function returns the tablespace data from config file"""
+
+    adv_config_data = None
+    data = None
+    db_user = server_connect['data']['user']['name']
+    server_config_data = config_data['server_credentials']
+
+    # Get the config data of appropriate db user
+    for config_test_data in advanced_config_data['tablespc_credentials']:
+        if db_user == config_test_data['spc_user']:
+            # Add the tablespace path from server config
+            server_config = (item for item in server_config_data if
+                             item["db_username"] == db_user).next()
+            config_test_data['spc_location'] = server_config['tablespace_path']
+            adv_config_data = config_test_data
+
+    if adv_config_data is not None:
+        data = {
+            "name": str(uuid.uuid4())[1:8],
+            "seclabels": adv_config_data["spc_seclable"],
+            "spcacl": adv_config_data["spc_acl"],
+            "spclocation": adv_config_data["spc_location"],
+            "spcoptions": adv_config_data["spc_opts"],
+            "spcuser": adv_config_data["spc_user"]
+        }
+    return data
+
+
+def write_tablespace_id(response_data):
+    """
+    This function write the table space id to parent_id.pkl
+
+    :param response_data: create table space API response data
+    :type response_data: dict
+    :return: None
+    """
+
+    table_space_id = response_data['node']['_id']
+    server_id = response_data['node']['_pid']
+    pickle_id_dict = utils.get_pickle_id_dict()
+    if os.path.isfile(pickle_path):
+        existing_server_id = open(pickle_path, 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+    if 'tsid' in pickle_id_dict:
+        if pickle_id_dict['tsid']:
+            # Add the db_id as value in dict
+            pickle_id_dict["tsid"][0].update(
+                {server_id: table_space_id})
+        else:
+            # Create new dict with server_id and db_id
+            pickle_id_dict["tsid"].append(
+                {server_id: table_space_id})
+    db_output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, db_output)
+    db_output.close()
+
+
+def add_table_space(tester, server_connect_response, server_group, server_ids):
+    """
+    This function is used to add the roles to server
+
+    :param tester: flask test client
+    :type tester: flask test client object
+    :param server_connect_response: server connect API response
+    :type server_connect_response: dict
+    :param server_group: server group
+    :type server_group: int
+    :param server_ids: list of server id
+    :type server_ids: list
+    :return: None
+    """
+
+    total_servers_count = len(server_ids)
+    servers_without_tablespace_path = []
+
+    for server_connect, server_id in zip(server_connect_response,
+                                         server_ids):
+        file_name = os.path.basename(sys._getframe().f_back.f_code.co_filename)
+        # Skip the test case if tablespace_path does not exist
+        if not str(server_connect['tablespace_path']):
+            servers_without_tablespace_path.append(server_id)
+            if total_servers_count == len(servers_without_tablespace_path):
+                print("Skipping tablespaces test cases for the  file <{0}>, "
+                      "Tablespace path not found for any of the server : "
+                      "{1}".format(file_name, server_ids), file=sys.stderr)
+                return
+            else:
+                print("Skipping tablespaces test case for the file <{0}>: "
+                      "Tablespace path not found for server : {1}".format(
+                        file_name, server_id), file=sys.stderr)
+                continue
+
+        if server_connect['data']['connected']:
+            data = get_tablespace_data(server_connect)
+            response = tester.post(TABLE_SPACE_URL + str(server_group) + '/'
+                                   + server_id + '/',
+                                   data=json.dumps(data),
+                                   content_type='html/json')
+            assert response.status_code == 200
+            response_data = json.loads(response.data.decode('utf-8'))
+            write_tablespace_id(response_data)
+
+
+def verify_table_space(tester, server_group, server_id, tablespace_id):
+    """
+    This function calls the GET API for role to verify
+
+    :param tester: test client
+    :type tester: flask test client object
+    :param server_group: server group id
+    :type server_group: int
+    :param server_id: server id
+    :type server_id: str
+    :param tablespace_id: table space id
+    :type tablespace_id: int
+    :return: dict/None
+    """
+
+    srv_connect = server_utils.verify_server(tester, server_group, server_id)
+    if srv_connect['data']['connected']:
+        response = tester.get(
+            '{0}{1}/{2}/{3}'.format(TABLE_SPACE_URL, server_group, server_id,
+                                    tablespace_id),
+            content_type='html/json')
+        assert response.status_code == 200
+        temp_response = json.loads(response.data.decode('utf-8'))
+        return temp_response
+    else:
+        return None
+
+
+def delete_table_space(tester):
+    """
+    This function use to delete the existing tablespace in the servers
+
+    :param tester: flask test client
+    :type tester: flask test object
+    :return: None
+    """
+
+    all_id = utils.get_ids()
+    server_ids = all_id["sid"]
+    if "tsid" in all_id and all_id["tsid"]:
+        tablespace_ids_dict = all_id["tsid"][0]
+    else:
+        tablespace_ids_dict = None
+
+    if tablespace_ids_dict is not None:
+        for server_id in server_ids:
+            tablespace_id = tablespace_ids_dict[int(server_id)]
+            role_response = verify_table_space(tester, utils.SERVER_GROUP,
+                                               server_id,
+                                               tablespace_id)
+            if len(role_response) == 0:
+                raise Exception("No tablespace(s) to delete!!!")
+            response = tester.delete(
+                TABLE_SPACE_URL + str(utils.SERVER_GROUP) + '/' +
+                str(server_id) + '/' + str(tablespace_id),
+                follow_redirects=True)
+            assert response.status_code == 200
+            delete_response_data = json.loads(response.data.decode('utf-8'))
+            assert delete_response_data['success'] == 1
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 2b1eb45..7348a47 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
@@ -7,10 +7,9 @@
 #
 # ##########################################################################
 
-import json
-
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
+from . import utils as server_utils
 
 
 class ServersAddTestCase(BaseTestGenerator):
@@ -21,24 +20,17 @@ class ServersAddTestCase(BaseTestGenerator):
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         pass
 
     def runTest(self):
         """ This function will add the server under default server group."""
 
-        server_group, config_data, pickle_id_dict = utils.get_config_data()
-        for server_data in config_data:
-            url = "{0}{1}/".format(self.url, server_group)
-            response = self.tester.post(url, data=json.dumps(server_data),
-                                        content_type='html/json')
-
-            self.assertTrue(response.status_code, 200)
-
-            response_data = json.loads(response.data.decode())
-            utils.write_parent_id(response_data, pickle_id_dict)
+        server_utils.add_server(self.tester)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the added server and the 'parent_id.pkl' file
         which is created in setup() function.
@@ -46,5 +38,5 @@ class ServersAddTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_server(self.tester)
+        server_utils.delete_server(cls.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
index 4fd207b..6431bec 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
@@ -7,12 +7,11 @@
 #
 # ##################################################################
 
-import json
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import config_data
-from regression.test_utils import get_ids
+
+from . import utils as server_utils
 
 
 class ServerDeleteTestCase(BaseTestGenerator):
@@ -23,7 +22,8 @@ class ServerDeleteTestCase(BaseTestGenerator):
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function is used to add the server
 
@@ -31,28 +31,16 @@ class ServerDeleteTestCase(BaseTestGenerator):
         """
 
         # Firstly, add the server
-        utils.add_server(self.tester)
+        server_utils.add_server(cls.tester)
 
     def runTest(self):
         """ This function will get all available servers under object browser
         and delete the last server using server id."""
 
-        srv_grp = config_data['test_server_group']
-        all_id = get_ids()
-        server_ids = all_id["sid"]
-
-        url = self.url + str(srv_grp) + "/"
-        if len(server_ids) == 0:
-            raise Exception("No server(s) to delete!!!")
-
-        # Call api to delete the servers
-        for server_id in server_ids:
-            response = self.tester.delete(url + str(server_id))
-            self.assertTrue(response.status_code, 200)
-            response_data = json.loads(response.data.decode())
-            self.assertTrue(response_data['success'], 1)
+        server_utils.delete_server(self.tester)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the 'parent_id.pkl' file which is created in
         setup() function.
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
index ea3c63f..e541247 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
@@ -9,8 +9,7 @@
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import config_data
-from regression.test_utils import get_ids
+from . import utils as server_utils
 
 
 class ServersGetTestCase(BaseTestGenerator):
@@ -24,28 +23,23 @@ class ServersGetTestCase(BaseTestGenerator):
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function is used to add the server
 
         :return: None
         """
 
-        utils.add_server(self.tester)
+        server_utils.add_server(cls.tester)
 
     def runTest(self):
         """ This function will fetch the added servers to object browser. """
 
-        all_id = get_ids()
-        server_ids = all_id["sid"]
-        srv_grp = config_data['test_server_group']
+        server_utils.get_server(self.tester)
 
-        for server_id in server_ids:
-            url = "{0}{1}/{2}".format(self.url, srv_grp, server_id)
-            response = self.tester.get(url, content_type='html/json')
-            self.assertEquals(response.status_code, 200)
-
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the added server and the 'parent_id.pkl' file
         which is created in setup() function.
@@ -53,5 +47,5 @@ class ServersGetTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_server(self.tester)
+        server_utils.delete_server(cls.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
index 5e810ba..9ac6468 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
@@ -8,10 +8,9 @@
 # ##########################################################################
 
 import json
-
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import config_data
+from . import utils as server_utils
 
 
 class ServerUpdateTestCase(BaseTestGenerator):
@@ -22,7 +21,8 @@ class ServerUpdateTestCase(BaseTestGenerator):
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function perform the four tasks
          1. Add the test server
@@ -33,13 +33,16 @@ class ServerUpdateTestCase(BaseTestGenerator):
         """
 
         # Firstly, add the server
-        utils.add_server(self.tester)
+        server_utils.add_server(cls.tester)
+
         # Get the server
-        utils.get_server(self.tester)
+        server_utils.get_server(cls.tester)
+
         # Connect to server
-        self.server_connect, self.server_group, self.server_ids = \
-            utils.connect_server(self.tester)
-        if len(self.server_connect) == 0:
+        cls.server_connect, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect) == 0:
             raise Exception("No Server(s) connected to update!!!")
 
     def runTest(self):
@@ -48,7 +51,8 @@ class ServerUpdateTestCase(BaseTestGenerator):
         for server_id in self.server_ids:
             data = {
                 "comment":
-                    config_data['test_server_update_data'][0]['test_comment'],
+                    server_utils.config_data['server_update_data'][0][
+                        'comment'],
                 "id": server_id
             }
             put_response = self.tester.put(
@@ -60,7 +64,8 @@ class ServerUpdateTestCase(BaseTestGenerator):
             response_data = json.loads(put_response.data.decode())
             self.assertTrue(response_data['success'], 1)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the added server and the 'parent_id.pkl' file
         which is created in setup() function.
@@ -68,5 +73,5 @@ class ServerUpdateTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_server(self.tester)
+        server_utils.delete_server(cls.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tests/utils.py b/web/pgadmin/browser/server_groups/servers/tests/utils.py
new file mode 100644
index 0000000..6e3f166
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tests/utils.py
@@ -0,0 +1,160 @@
+# ##########################################################################
+#
+# #pgAdmin 4 - PostgreSQL Tools
+#
+# #Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# #This software is released under the PostgreSQL Licence
+#
+# ##########################################################################
+
+import json
+import os
+import pickle
+
+from regression import test_utils as utils
+from regression.test_setup import pickle_path, config_data
+
+SERVER_URL = '/browser/server/obj/'
+SERVER_CONNECT_URL = 'browser/server/connect/'
+
+
+def write_server_id(response_data, pickle_id_dict):
+    """
+    This function writes the server's details to file parent_id.pkl
+
+    :param response_data: server's data
+    :type response_data: list of dictionary
+    :param pickle_id_dict: contains ids of server,database,tables etc.
+    :type pickle_id_dict: dict
+    :return: None
+    """
+
+    server_id = response_data['node']['_id']
+    if os.path.isfile(pickle_path):
+        existed_server_id = open(pickle_path, 'rb')
+        pickle_id_dict = pickle.load(existed_server_id)
+
+    pickle_id_dict["sid"].append(str(server_id))
+    output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, output)
+    output.close()
+
+
+def add_server(tester):
+    """
+    This function add the server in the existing server group
+
+    :param tester: test object
+    :type tester: flask test object
+    :return:None
+    """
+
+    server_group, db_data, pickle_id_dict = utils.get_config_data()
+    url = "{0}{1}/".format(SERVER_URL, server_group)
+    for db_detail in db_data:
+        response = tester.post(url, data=json.dumps(db_detail),
+                               content_type='html/json')
+        assert response.status_code == 200
+        response_data = json.loads(response.data.decode('utf-8'))
+        write_server_id(response_data, pickle_id_dict)
+
+
+def get_server(tester):
+    """
+    This function gets the added serer details
+
+    :param tester: test client object
+    :type tester: flask test object
+    :return: response_data
+    :rtype: list
+    """
+
+    all_id = utils.get_ids()
+    server_ids = all_id["sid"]
+    for server_id in server_ids:
+        response = tester.get(SERVER_URL + str(utils.SERVER_GROUP) + '/' +
+                              str(server_id),
+                              follow_redirects=True)
+        assert response.status_code == 200
+
+
+def connect_server(tester):
+    """
+    This function used to connect added server
+
+    :param tester:test client object
+    :type tester: flask test object
+    :param add_db_flag: flag for db add test case
+    :type add_db_flag: bool
+    :return: server_connect, server_group, server_id
+    :rtype: server_connect:dict, server_group:dict, server_id:str
+    """
+
+    server_connect = []
+    servers = []
+    server_config = None
+
+    srv_id = utils.get_ids()
+    server_ids = srv_id["sid"]
+
+    # Connect to all servers
+    for server_id in server_ids:
+        response = tester.post(SERVER_CONNECT_URL + str(utils.SERVER_GROUP) +
+                               '/' + server_id,
+                               data=dict(
+                                   password=config_data
+                                   ['server_credentials'][0]
+                                   ['db_password']),
+                               follow_redirects=True)
+        server_connect_detail = json.loads(response.data.decode('utf-8'))
+        db_user = server_connect_detail['data']['user']['name']
+        server_connect_detail['tablespace_path'] = None
+
+        # Get the server config of appropriate db user
+        for config in config_data['server_credentials']:
+            if db_user == config['db_username']:
+                server_config = config
+
+        if "tablespace_path" in server_config:
+            server_connect_detail['tablespace_path'] = \
+                server_config['tablespace_path']
+
+        server_connect.append(server_connect_detail)
+        servers.append(server_id)
+    return server_connect, utils.SERVER_GROUP, servers
+
+
+def verify_server(tester, server_group, server_id):
+    """This function verifies that server is connecting or not"""
+
+    response = tester.post(
+        '{0}{1}/{2}'.format(SERVER_CONNECT_URL, server_group, server_id),
+        data=dict(password=config_data
+        ['server_credentials'][0]
+        ['db_password']),
+        follow_redirects=True)
+    srv_connect = json.loads(response.data.decode('utf-8'))
+    return srv_connect
+
+
+def delete_server(tester):
+    """
+    This function used to delete the added servers
+
+    :param tester: test client object
+    :return: None
+    """
+
+    all_id = utils.get_ids()
+    server_ids = all_id["sid"]
+    url = SERVER_URL + str(utils.SERVER_GROUP) + "/"
+
+    if len(server_ids) == 0:
+        raise Exception("No server(s) to delete!!!")
+
+    # Call api to delete the servers
+    for server_id in server_ids:
+        response = tester.delete(url + str(server_id))
+        assert response.status_code == 200
+        response_data = json.loads(response.data.decode('utf-8'))
+        assert response_data['success'] == 1
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/tests/test_sg_get.py b/web/pgadmin/browser/server_groups/tests/test_sg_get.py
index 6c164be..5df67c9 100644
--- a/web/pgadmin/browser/server_groups/tests/test_sg_get.py
+++ b/web/pgadmin/browser/server_groups/tests/test_sg_get.py
@@ -26,7 +26,7 @@ class SgNodeTestCase(BaseTestGenerator):
     def runTest(self):
         """This function will check available server groups."""
 
-        server_group_id = config_data['test_server_group']
+        server_group_id = config_data['server_group']
         response = self.tester.get(self.url + str(server_group_id),
                                    content_type='html/json')
         self.assertTrue(response.status_code, 200)
diff --git a/web/pgadmin/browser/tests/test_change_password.py b/web/pgadmin/browser/tests/test_change_password.py
index 2f714a7..5b7c918 100644
--- a/web/pgadmin/browser/tests/test_change_password.py
+++ b/web/pgadmin/browser/tests/test_change_password.py
@@ -8,9 +8,12 @@
 # ##########################################################################
 
 import uuid
+import json
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression.test_setup import config_data
+from regression import test_utils as utils
+from utils import change_password
 
 
 class ChangePasswordTestCase(BaseTestGenerator):
@@ -24,9 +27,9 @@ class ChangePasswordTestCase(BaseTestGenerator):
         # This testcase validates invalid confirmation password
         ('TestCase for Validating Incorrect_New_Password', dict(
             password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password']),
+                      ['login_password']),
             new_password=(config_data['pgAdmin4_login_credentials']
-                          ['test_new_password']),
+                          ['new_password']),
             new_password_confirm=str(uuid.uuid4())[4:8],
             respdata='Passwords do not match')),
 
@@ -34,7 +37,7 @@ class ChangePasswordTestCase(BaseTestGenerator):
         # minimum length
         ('TestCase for Validating New_Password_Less_Than_Min_Length',
          dict(password=(config_data['pgAdmin4_login_credentials']
-                        ['test_login_password']),
+                        ['login_password']),
               new_password=str(uuid.uuid4())[4:8],
               new_password_confirm=str(uuid.uuid4())[4:8],
               respdata='Password must be at least 6 characters')),
@@ -42,7 +45,7 @@ class ChangePasswordTestCase(BaseTestGenerator):
         # This testcase validates if both password fields are left blank
         ('TestCase for Validating Empty_New_Password', dict(
             password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password']),
+                      ['login_password']),
             new_password='', new_password_confirm='',
             respdata='Password not provided')),
 
@@ -50,57 +53,66 @@ class ChangePasswordTestCase(BaseTestGenerator):
         ('TestCase for Validating Incorrect_Current_Password', dict(
             password=str(uuid.uuid4())[4:8],
             new_password=(config_data['pgAdmin4_login_credentials']
-                          ['test_new_password']),
+                          ['new_password']),
             new_password_confirm=(
                 config_data['pgAdmin4_login_credentials']
-                ['test_new_password']),
+                ['new_password']),
             respdata='Invalid password')),
 
-        # This testcase checks for valid password
+        # This test case checks for valid password
         ('TestCase for Changing Valid_Password', dict(
-            password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password']),
-            new_password=(config_data['pgAdmin4_login_credentials']
-                          ['test_new_password']),
-            new_password_confirm=(
-                config_data['pgAdmin4_login_credentials']
-                ['test_new_password']),
-            respdata='You successfully changed your password.')),
-        ('Reassigning_Password', dict(
-            test_case='reassigning_password',
-            password=(config_data['pgAdmin4_login_credentials']
-                      ['test_new_password']),
-            new_password=(config_data['pgAdmin4_login_credentials']
-                          ['test_login_password']),
+            valid_password='reassigning_password',
+            username=(config_data['pgAdmin4_test_user_credentials']
+                      ['login_username']),
+            password=(config_data['pgAdmin4_test_user_credentials']
+                      ['login_password']),
+            new_password=(config_data['pgAdmin4_test_user_credentials']
+                          ['new_password']),
             new_password_confirm=(
-                config_data['pgAdmin4_login_credentials']
-                ['test_login_password']),
+                config_data['pgAdmin4_test_user_credentials']
+                ['new_password']),
             respdata='You successfully changed your password.'))
-
     ]
 
+    @classmethod
+    def setUpClass(cls):
+        pass
+
     def runTest(self):
         """This function will check change password functionality."""
 
-        # Check for 'test_case' exists in self For reassigning the password.
-        # Password gets change in change password test case.
-        if 'test_case' in dir(self):
-            email = \
-                config_data['pgAdmin4_login_credentials'][
-                    'test_login_username']
-            password = \
-                config_data['pgAdmin4_login_credentials'][
-                    'test_new_password']
+        # Check for 'valid_password' exists in self to test 'valid password'
+        # test case
+        if 'valid_password' in dir(self):
+            response = self.tester.post('/user_management/user/', data=dict(
+                email=self.username, newPassword=self.password,
+                confirmPassword=self.password, active=1, role="2"),
+                                        follow_redirects=True)
+            user_id = json.loads(response.data.decode('utf-8'))['id']
+
+            # Logout the Administrator before login normal user
+            utils.logout_tester_account(self.tester)
+
             response = self.tester.post('/login', data=dict(
-                email=email, password=password), follow_redirects=True)
-
-        response = self.tester.get('/change', follow_redirects=True)
-        self.assertIn('pgAdmin 4 Password Change', response.data.decode(
-            'utf-8'))
-
-        response = self.tester.post('/change', data=dict(
-            password=self.password,
-            new_password=self.new_password,
-            new_password_confirm=self.new_password_confirm),
-                                    follow_redirects=True)
-        self.assertIn(self.respdata, response.data.decode('utf-8'))
+                email=self.username, password=self.password),
+                                        follow_redirects=True)
+            assert response.status_code == 200
+
+            # test the 'change password' test case
+            change_password(self)
+
+            # Delete the normal user after changing it's password
+            utils.logout_tester_account(self.tester)
+
+            # Login the Administrator before deleting normal user
+            utils.login_tester_account(self.tester)
+            response = self.tester.delete(
+                '/user_management/user/' + str(user_id),
+                follow_redirects=True)
+            assert response.status_code == 200
+        else:
+            change_password(self)
+
+    @classmethod
+    def tearDownClass(cls):
+        utils.login_tester_account(cls.tester)
diff --git a/web/pgadmin/browser/tests/test_login.py b/web/pgadmin/browser/tests/test_login.py
index b0ea361..f6bc6b5 100644
--- a/web/pgadmin/browser/tests/test_login.py
+++ b/web/pgadmin/browser/tests/test_login.py
@@ -24,20 +24,20 @@ class LoginTestCase(BaseTestGenerator):
         # This test case validates the invalid/incorrect password
         ('TestCase for Checking Invalid_Password', dict(
             email=(config_data['pgAdmin4_login_credentials']
-                   ['test_login_username']),
+                   ['login_username']),
             password=str(uuid.uuid4())[4:8],
             respdata='Invalid password')),
 
         # This test case validates the empty password field
         ('Empty_Password', dict(
             email=(config_data['pgAdmin4_login_credentials']
-                   ['test_login_username']), password='',
+                   ['login_username']), password='',
             respdata='Password not provided')),
 
         # This test case validates blank email field
         ('Empty_Email', dict(
             email='', password=(config_data['pgAdmin4_login_credentials']
-                                ['test_login_password']),
+                                ['login_password']),
             respdata='Email not provided')),
 
         # This test case validates empty email and password
@@ -49,7 +49,7 @@ class LoginTestCase(BaseTestGenerator):
         ('Invalid_Email', dict(
             email=str(uuid.uuid4())[1:6] + '@xyz.com',
             password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password']),
+                      ['login_password']),
             respdata='Specified user does not exist')),
 
         # This test case validates invalid email and password
@@ -62,21 +62,22 @@ class LoginTestCase(BaseTestGenerator):
         # to login pgAdmin 4
         ('Valid_Credentials', dict(
             email=(config_data['pgAdmin4_login_credentials']
-                   ['test_login_username']),
+                   ['login_username']),
             password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password']),
+                      ['login_password']),
             respdata='Gravatar image for %s' %
                      config_data['pgAdmin4_login_credentials']
-                     ['test_login_username']))
+                     ['login_username']))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         We need to logout the test client as we are testing scenarios of
         logging in the client like invalid password, invalid emails,
         empty credentials etc.
         """
-        utils.logout_tester_account(self.tester)
+        utils.logout_tester_account(cls.tester)
 
     def runTest(self):
         """This function checks login functionality."""
@@ -86,9 +87,10 @@ class LoginTestCase(BaseTestGenerator):
                                     follow_redirects=True)
         self.assertIn(self.respdata, response.data.decode('utf8'))
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         We need to again login the test client as soon as test scenarios
         finishes.
         """
-        utils.login_tester_account(self.tester)
+        utils.login_tester_account(cls.tester)
diff --git a/web/pgadmin/browser/tests/test_logout.py b/web/pgadmin/browser/tests/test_logout.py
index 729f7b1..5697de6 100644
--- a/web/pgadmin/browser/tests/test_logout.py
+++ b/web/pgadmin/browser/tests/test_logout.py
@@ -24,7 +24,8 @@ class LogoutTest(BaseTestGenerator):
         ('Logging Out', dict(respdata='Redirecting...'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         pass
 
     def runTest(self):
@@ -33,9 +34,10 @@ class LogoutTest(BaseTestGenerator):
         response = self.tester.get('/logout')
         self.assertIn(self.respdata, response.data.decode('utf8'))
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         We need to again login the test client as soon as test scenarios
         finishes.
         """
-        utils.login_tester_account(self.tester)
+        utils.login_tester_account(cls.tester)
diff --git a/web/pgadmin/browser/tests/test_reset_password.py b/web/pgadmin/browser/tests/test_reset_password.py
index 9420c72..0dcf0bd 100644
--- a/web/pgadmin/browser/tests/test_reset_password.py
+++ b/web/pgadmin/browser/tests/test_reset_password.py
@@ -34,11 +34,12 @@ class ResetPasswordTestCase(BaseTestGenerator):
         # This test case validates the valid email id
         ('TestCase for Validating Valid_Email', dict(
             email=config_data['pgAdmin4_login_credentials']
-            ['test_login_username'], respdata='pgAdmin 4'))
+            ['login_username'], respdata='pgAdmin 4'))
     ]
 
-    def setUp(self):
-        logout_tester_account(self.tester)
+    @classmethod
+    def setUpClass(cls):
+        logout_tester_account(cls.tester)
 
     def runTest(self):
         """This function checks reset password functionality."""
@@ -51,5 +52,6 @@ class ResetPasswordTestCase(BaseTestGenerator):
             follow_redirects=True)
         self.assertIn(self.respdata, response.data.decode('utf-8'))
 
-    def tearDown(self):
-        login_tester_account(self.tester)
+    @classmethod
+    def tearDownClass(cls):
+        login_tester_account(cls.tester)
diff --git a/web/pgadmin/browser/tests/utils.py b/web/pgadmin/browser/tests/utils.py
new file mode 100644
index 0000000..18548ce
--- /dev/null
+++ b/web/pgadmin/browser/tests/utils.py
@@ -0,0 +1,21 @@
+# ##########################################################################
+#
+# #pgAdmin 4 - PostgreSQL Tools
+#
+# #Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# #This software is released under the PostgreSQL Licence
+#
+# ##########################################################################
+
+
+def change_password(self):
+    response = self.tester.get('/change', follow_redirects=True)
+    self.assertIn('pgAdmin 4 Password Change', response.data.decode(
+        'utf-8'))
+
+    response = self.tester.post('/change', data=dict(
+        password=self.password,
+        new_password=self.new_password,
+        new_password_confirm=self.new_password_confirm),
+                                follow_redirects=True)
+    self.assertIn(self.respdata, response.data.decode('utf-8'))
\ No newline at end of file
diff --git a/web/pgadmin/utils/route.py b/web/pgadmin/utils/route.py
index c7ef1f8..0226e8d 100644
--- a/web/pgadmin/utils/route.py
+++ b/web/pgadmin/utils/route.py
@@ -84,5 +84,6 @@ class BaseTestGenerator(unittest.TestCase):
         self.app = app
 
     # Initializing test_client.
-    def setTestClient(self, test_client):
-        self.tester = test_client
+    @classmethod
+    def setTestClient(cls, test_client):
+        cls.tester = test_client
diff --git a/web/regression/test_advanced_config.json.in b/web/regression/test_advanced_config.json.in
index c0d278b..fc8d98f 100644
--- a/web/regression/test_advanced_config.json.in
+++ b/web/regression/test_advanced_config.json.in
@@ -1,7 +1,7 @@
 {
-  "test_add_database_data": [
+  "add_database_data": [
    {
-    "test_privileges_acl": [
+    "privileges_acl": [
       {
         "grantee": "postgres",
         "grantor": "postgres",
@@ -19,9 +19,9 @@
         ]
       }
     ],
-    "test_conn_limit": -1,
-    "test_owner": "postgres",
-    "test_fun_acl": [
+    "conn_limit": -1,
+    "owner": "postgres",
+    "fun_acl": [
       {
         "grantee": "postgres",
         "grantor": "postgres",
@@ -34,7 +34,7 @@
         ]
       }
     ],
-    "test_seq_acl": [
+    "seq_acl": [
       {
         "grantee": "postgres",
         "grantor": "postgres",
@@ -57,7 +57,7 @@
         ]
       }
     ],
-    "test_tbl_acl": [
+    "tbl_acl": [
       {
         "grantee": "postgres",
         "grantor": "postgres",
@@ -75,7 +75,7 @@
         ]
       }
     ],
-    "test_type_acl": [
+    "type_acl": [
       {
         "grantee": "postgres",
         "grantor": "postgres",
@@ -88,112 +88,60 @@
         ]
       }
     ],
-    "test_encoding": "UTF8",
-    "test_name": "test_db_automation",
-    "test_privileges": [],
-    "test_securities": [],
-    "test_variables": []
-  },
-       {
-         "test_privileges_acl": [
-           {
-             "grantee": "enterprisedb",
-             "grantor": "enterprisedb",
-             "privileges": [
-               {
-                 "privilege_type": "C",
-                 "privilege": true,
-                 "with_grant": true
-               },
-               {
-                 "privilege_type": "T",
-                 "privilege": true,
-                 "with_grant": false
-               }
-             ]
-           }
-         ],
-         "test_conn_limit": -1,
-         "test_owner": "enterprisedb",
-         "test_fun_acl": [
-           {
-             "grantee": "enterprisedb",
-             "grantor": "enterprisedb",
-             "privileges": [
-               {
-                 "privilege_type": "X",
-                 "privilege": true,
-                 "with_grant": false
-               }
-             ]
-           }
-         ],
-         "test_seq_acl": [
-           {
-             "grantee": "enterprisedb",
-             "grantor": "enterprisedb",
-             "privileges": [
-               {
-                 "privilege_type": "r",
-                 "privilege": true,
-                 "with_grant": false
-               },
-               {
-                 "privilege_type": "w",
-                 "privilege": true,
-                 "with_grant": false
-               },
-               {
-                 "privilege_type": "U",
-                 "privilege": true,
-                 "with_grant": false
-               }
-             ]
-           }
-         ],
-         "test_tbl_acl": [
-           {
-             "grantee": "enterprisedb",
-             "grantor": "enterprisedb",
-             "privileges": [
-               {
-                 "privilege_type": "a",
-                 "privilege": true,
-                 "with_grant": true
-               },
-               {
-                 "privilege_type": "r",
-                 "privilege": true,
-                 "with_grant": false
-               }
-             ]
-           }
-         ],
-         "test_type_acl": [
-           {
-             "grantee": "enterprisedb",
-             "grantor": "enterprisedb",
-             "privileges": [
-               {
-                 "privilege_type": "U",
-                 "privilege": true,
-                 "with_grant": false
-               }
-             ]
-           }
-         ],
-         "test_encoding": "UTF8",
-         "test_name": "test_db_automation",
-         "test_privileges": [],
-         "test_securities": [],
-         "test_variables": []
-       }
+    "encoding": "UTF8",
+    "name": "test_db_automation",
+    "privileges": [],
+    "securities": [],
+    "variables": []
+  }
  ],
-
-  "test_db_update_data": [
+  "db_update_data": [
   {
-      "test_comment": "This is db update comment"
+      "comment": "This is db update comment"
   }
- ]
+ ],
+
+  "lr_credentials": {
+      "can_login": "true",
+      "conn_limit": -1,
+      "create_role": "true",
+      "role_inherit": "true",
+      "role_membership": [],
+      "lr_name":  "testlrg1",
+      "lr_password": "edb",
+      "lr_validity": "12/27/2016",
+      "sec_lable": [],
+      "variable":[
+                        {"name":"work_mem",
+                          "database":"postgres",
+                          "value":65
+                        }]
+    },
+  "lr_update_data": {
+      "comment": "This is db update comment"
+  },
+
+  "tablespc_credentials":[{
+    "tblspace_name": "test_tablespace",
+    "spc_seclable": [],
+    "spc_acl": [
+      {
+        "grantee":"postgres",
+        "grantor":"postgres",
+        "privileges":[
+          {
+            "privilege_type":"C",
+            "privilege":true,
+            "with_grant":false
+          }
+        ]
+      }
+    ],
+    "spc_opts": [],
+    "spc_user": "postgres"
+  }],
 
+    "tbspc_update_data": {
+    "comment": "This is tablespace update comment"
+  }
 }
\ No newline at end of file
diff --git a/web/regression/test_config.json.in b/web/regression/test_config.json.in
index 028d1e7..1328b6b 100644
--- a/web/regression/test_config.json.in
+++ b/web/regression/test_config.json.in
@@ -1,35 +1,31 @@
 {
   "pgAdmin4_login_credentials": {
-    "test_new_password": "NEWPASSWORD",
-    "test_login_password": "PASSWORD",
-    "test_login_username": "[email protected]"
+    "new_password": "NEWPASSWORD",
+    "login_password": "PASSWORD",
+    "login_username": "[email protected]"
   },
-  "test_server_group": 1,
-  "test_server_credentials": [
+  "pgAdmin4_test_user_credentials": {
+    "new_password": "NEWPASSWORD",
+    "login_password": "PASSWORD",
+    "login_username": "[email protected]"
+  },
+  "server_group": 1,
+  "server_credentials": [
     {
-      "test_name": "PostgreSQL 9.4",
-      "test_comment": "PostgreSQL 9.4 Server (EDB Installer)",
-      "test_db_username": "postgres",
-      "test_host": "localhost",
-      "test_db_password": "PASSWORD",
-      "test_db_port": 5432,
-      "test_maintenance_db": "postgres",
-      "test_sslmode": "prefer"
-    },
-     {
-       "test_name": "Postgres Plus Advanced Server 9.4",
-       "test_comment": "Postgres Plus Advanced 9.4 Server (EDB Installer)",
-       "test_db_username": "enterprisedb",
-       "test_host": "localhost",
-       "test_db_password": "edb",
-       "test_db_port": 5444,
-       "test_maintenance_db": "edb",
-       "test_sslmode": "prefer"
-     }
+      "name": "PostgreSQL 9.4",
+      "comment": "PostgreSQL 9.4 Server (EDB Installer)",
+      "db_username": "postgres",
+      "host": "localhost",
+      "db_password": "PASSWORD",
+      "db_port": 5432,
+      "maintenance_db": "postgres",
+      "sslmode": "prefer",
+      "tablespace_path": ""
+    }
   ],
-  "test_server_update_data": [
+  "server_update_data": [
     {
-      "test_comment": "This is test update comment"
+      "comment": "This is test update comment"
     }
   ]
 }
\ No newline at end of file
diff --git a/web/regression/test_setup.py b/web/regression/test_setup.py
index f7765bc..c805b1e 100644
--- a/web/regression/test_setup.py
+++ b/web/regression/test_setup.py
@@ -12,10 +12,24 @@ import os
 
 CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
 
-with open(CURRENT_PATH + '/test_config.json') as data_file:
-    config_data = json.load(data_file)
+# with open(CURRENT_PATH + '/test_config.json') as data_file:
+#     config_data = json.load(data_file)
+#
+# with open(CURRENT_PATH + '/test_advanced_config.json') as data_file:
+#     advanced_config_data = json.load(data_file)
+
+try:
+    with open(CURRENT_PATH + '/test_config.json') as data_file:
+        config_data = json.load(data_file)
+except:
+    with open(CURRENT_PATH + '/test_config.json.in') as data_file:
+        config_data = json.load(data_file)
 
-with open(CURRENT_PATH + '/test_advanced_config.json') as data_file:
-    advanced_config_data = json.load(data_file)
+try:
+    with open(CURRENT_PATH + '/test_advanced_config.json') as data_file:
+        advanced_config_data = json.load(data_file)
+except:
+    with open(CURRENT_PATH + '/test_advanced_config.json.in') as data_file:
+        advanced_config_data = json.load(data_file)
 
 pickle_path = os.path.join(CURRENT_PATH, 'parent_id.pkl')
diff --git a/web/regression/test_utils.py b/web/regression/test_utils.py
index 6be2bb2..16c2d46 100644
--- a/web/regression/test_utils.py
+++ b/web/regression/test_utils.py
@@ -9,16 +9,24 @@
 
 import os
 import pickle
-import json
-import uuid
 
-from test_setup import config_data, advanced_config_data, \
-    pickle_path
+from test_setup import config_data, pickle_path
 
-SERVER_URL = '/browser/server/obj/'
-SERVER_CONNECT_URL = 'browser/server/connect/'
-DATABASE_URL = '/browser/database/obj/'
-DATABASE_CONNECT_URL = 'browser/database/connect/'
+
+SERVER_GROUP = config_data['server_group']
+
+
+def get_pickle_id_dict():
+    """This function returns the empty dict of server config data"""
+
+    pickle_id_dict = {
+        "sid": [],  # server
+        "did": [],  # database
+        "lrid": [],  # role
+        "tsid": [],  # tablespace
+        "scid": []  # schema
+    }
+    return pickle_id_dict
 
 
 def get_ids(url=pickle_path):
@@ -34,43 +42,9 @@ def get_ids(url=pickle_path):
     output = open(url, 'rb')
     ids = pickle.load(output)
     output.close()
-
     return ids
 
 
-def verify_database(tester, server_group, server_id, db_id):
-    """
-    This function verifies that database is exists and whether it connect
-    successfully or not
-
-    :param tester: test client
-    :type tester: flask test client object
-    :param server_group: server group id
-    :type server_group: int
-    :param server_id: server id
-    :type server_id: str
-    :param db_id: database id
-    :type db_id: str
-    :return: temp_db_con
-    :rtype: list
-    """
-
-    # Connect to server
-    response = tester.post('{0}{1}/{2}'.format(
-        SERVER_CONNECT_URL, server_group, server_id), data=dict(
-        password=config_data['test_server_credentials'][0][
-            'test_db_password']),
-        follow_redirects=True)
-
-    # Connect to database
-    con_response = tester.post('{0}{1}/{2}/{3}'.format(
-        DATABASE_CONNECT_URL, server_group, server_id, db_id),
-        follow_redirects=True)
-    temp_db_con = json.loads(con_response.data.decode('utf-8'))
-
-    return temp_db_con
-
-
 def test_getnodes(tester=None):
     # Connect to server and database.
 
@@ -81,53 +55,14 @@ def test_getnodes(tester=None):
 
     server_ids = all_id["sid"]
     db_ids_dict = all_id["did"][0]
-    srv_grp = config_data['test_server_group']
 
     db_con = []
     for server_id in server_ids:
         db_id = db_ids_dict[int(server_id)]
-        db_con.append(verify_database(tester, srv_grp, server_id, db_id))
+        db_con.append(verify_database(tester, SERVER_GROUP, server_id, db_id))
     return db_con
 
 
-def get_db_data(server_connect_data):
-    """
-    This function is used to get advance config test data for appropriate
-    server
-
-    :param server_connect_data: list of server details
-    :return data: database details
-    :rtype: dict
-    """
-
-    adv_config_data = None
-    data = None
-    db_user = server_connect_data['data']['user']['name']
-
-    # Get the config data of appropriate db user
-    for config_test_data in advanced_config_data['test_add_database_data']:
-        if db_user == config_test_data['test_owner']:
-            adv_config_data = config_test_data
-
-    if adv_config_data is not None:
-        data = {
-            "datacl": adv_config_data['test_privileges_acl'],
-            "datconnlimit": adv_config_data['test_conn_limit'],
-            "datowner": adv_config_data['test_owner'],
-            "deffuncacl": adv_config_data['test_fun_acl'],
-            "defseqacl": adv_config_data['test_seq_acl'],
-            "deftblacl": adv_config_data['test_tbl_acl'],
-            "deftypeacl": adv_config_data['test_type_acl'],
-            "encoding": adv_config_data['test_encoding'],
-            "name": str(uuid.uuid4())[1:8],
-            "privileges": adv_config_data['test_privileges'],
-            "securities": adv_config_data['test_securities'],
-            "variables": adv_config_data['test_variables']
-        }
-
-    return data
-
-
 def login_tester_account(tester):
     """
     This function login the test account using credentials mentioned in
@@ -139,9 +74,9 @@ def login_tester_account(tester):
     """
 
     email = \
-        config_data['pgAdmin4_login_credentials']['test_login_username']
+        config_data['pgAdmin4_login_credentials']['login_username']
     password = \
-        config_data['pgAdmin4_login_credentials']['test_login_password']
+        config_data['pgAdmin4_login_credentials']['login_password']
     response = tester.post('/login', data=dict(
         email=email, password=password), follow_redirects=True)
 
@@ -158,6 +93,7 @@ def logout_tester_account(tester):
     response = tester.get('/logout')
 
 
+# Config data for parent_id.pkl
 def get_config_data():
     """
     This function get the data related to server group and database
@@ -168,23 +104,18 @@ def get_config_data():
     """
 
     db_data = []
+    pickle_id_dict = get_pickle_id_dict()
+    server_group = config_data['server_group']
 
-    pickle_id_dict = {
-        "sid": [],  # server
-        "did": []  # database
-    }
-
-    server_group = config_data['test_server_group']
-
-    for srv in config_data['test_server_credentials']:
-        data = {"name": srv['test_name'],
+    for srv in config_data['server_credentials']:
+        data = {"name": srv['name'],
                 "comment": "",
-                "host": srv['test_host'],
-                "port": srv['test_db_port'],
-                "db": srv['test_maintenance_db'],
-                "username": srv['test_db_username'],
+                "host": srv['host'],
+                "port": srv['db_port'],
+                "db": srv['maintenance_db'],
+                "username": srv['db_username'],
                 "role": "",
-                "sslmode": srv['test_sslmode']}
+                "sslmode": srv['sslmode']}
         db_data.append(data)
     return server_group, db_data, pickle_id_dict
 
@@ -205,40 +136,12 @@ def write_parent_id(response_data, pickle_id_dict):
         existed_server_id = open(pickle_path, 'rb')
         pickle_id_dict = pickle.load(existed_server_id)
 
-    pickle_id_dict["sid"].append(server_id)
+    pickle_id_dict["sid"].append(str(server_id))
     output = open(pickle_path, 'wb')
     pickle.dump(pickle_id_dict, output)
     output.close()
 
 
-def write_db_parent_id(response_data):
-    """
-    This function writes the server and database related data like server
-    name, server id , database name, database id etc.
-
-    :param response_data: server and databases details
-    :type response_data: dict
-    :return: None
-    """
-
-    db_id = response_data['node']['_id']
-    server_id = response_data['node']['_pid']
-    if os.path.isfile(pickle_path):
-        existing_server_id = open(pickle_path, 'rb')
-        tol_server_id = pickle.load(existing_server_id)
-        pickle_id_dict = tol_server_id
-        if 'did' in pickle_id_dict:
-            if pickle_id_dict['did']:
-                # Add the db_id as value in dict
-                pickle_id_dict["did"][0].update({server_id: db_id})
-            else:
-                # Create new dict with server_id and db_id
-                pickle_id_dict["did"].append({server_id: db_id})
-        db_output = open(pickle_path, 'wb')
-        pickle.dump(pickle_id_dict, db_output)
-        db_output.close()
-
-
 def delete_parent_id_file():
     """
     This function deletes the file parent_id.pkl which contains server and
@@ -250,148 +153,3 @@ def delete_parent_id_file():
     if os.path.isfile(pickle_path):
         os.remove(pickle_path)
 
-
-def add_server(tester):
-    """
-    This function add the server in the existing server group
-
-    :param tester: test object
-    :type tester: flask test object
-    :return:None
-    """
-
-    server_group, db_data, pickle_id_dict = get_config_data()
-    url = "{0}{1}/".format(SERVER_URL, server_group)
-    for db_detail in db_data:
-        response = tester.post(url, data=json.dumps(db_detail),
-                               content_type='html/json')
-        response_data = json.loads(response.data.decode())
-        write_parent_id(response_data, pickle_id_dict)
-
-
-def get_server(tester):
-    """
-    This function gets the added serer details
-
-    :param tester: test client object
-    :type tester: flask test object
-    :return: response_data
-    :rtype: list
-    """
-
-    all_id = get_ids()
-    server_ids = all_id["sid"]
-    server_group = config_data['test_server_group']
-    for server_id in server_ids:
-        response = tester.get(SERVER_URL + str(server_group) + '/' +
-                              str(server_id),
-                              follow_redirects=True)
-        response_data = json.loads(response.data.decode())
-
-
-def connect_server(tester):
-    """
-    This function used to connect added server
-
-    :param tester:test client object
-    :type tester: flask test object
-    :return: server_connect, server_group, server_id
-    :rtype: server_connect:dict, server_group:dict, server_id:str
-    """
-
-    server_connect = []
-    servers = []
-
-    srv_id = get_ids()
-    server_ids = srv_id["sid"]
-    server_group = config_data['test_server_group']
-
-    # Connect to all servers
-    for server_id in server_ids:
-        response = tester.post(SERVER_CONNECT_URL + str(server_group) +
-                               '/' + server_id,
-                               data=dict(
-                                   password=config_data
-                                   ['test_server_credentials'][0]
-                                   ['test_db_password']),
-                               follow_redirects=True)
-        server_connect_detail = json.loads(response.data.decode())
-        connect_database(tester, server_connect_detail, server_id,
-                         server_group)
-        server_connect.append(server_connect_detail)
-        servers.append(server_id)
-    return server_connect, server_group, servers
-
-
-def connect_database(tester, server_connect, server_id, server_group):
-    """
-    This function is used to connect database and writes it's details to
-    file 'parent_id.pkl'
-
-    :param tester: test client object
-    :type tester: flask test client object
-    :param server_connect: server's data
-    :type server_connect: dict
-    :param server_id: server id
-    :type server_id: str
-    :param server_group: server group name
-    :type server_group: str
-    :return: None
-    """
-
-    if server_connect['data']['connected']:
-        db_data = get_db_data(server_connect)
-        db_response = tester.post(
-            DATABASE_URL + str(server_group) + "/" + server_id + "/",
-            data=json.dumps(db_data),
-            content_type='html/json')
-        response_data = json.loads(db_response.data.decode())
-        write_db_parent_id(response_data)
-
-
-def delete_server(tester):
-    """
-    This function used to delete the added servers
-
-    :param tester: test client object
-    :return: None
-    """
-
-    srv_grp = config_data['test_server_group']
-    all_id = get_ids()
-    server_ids = all_id["sid"]
-    url = SERVER_URL + str(srv_grp) + "/"
-
-    # Call api to delete the servers
-    for server_id in server_ids:
-        response = tester.delete(url + str(server_id))
-        assert response.status_code == 200
-        response_data = json.loads(response.data.decode())
-        assert response_data['success'] == 1
-
-
-def delete_database(tester):
-    """
-    This function used to delete the added databases
-
-    :param tester: test client object
-    :return: None
-    """
-
-    srv_grp = config_data['test_server_group']
-    all_id = get_ids()
-    server_ids = all_id["sid"]
-    db_ids_dict = all_id['did'][0]
-
-    db_con = test_getnodes(tester)
-    if len(db_con) == 0:
-        raise Exception("No database(s) to delete.")
-
-    for server_id in server_ids:
-        db_id = db_ids_dict[int(server_id)]
-        response = tester.delete(DATABASE_URL + str(srv_grp) + '/' +
-                                 str(server_id) + '/' + str(db_id),
-                                 follow_redirects=True)
-        assert response.status_code == 200
-        response_data = json.loads(response.data.decode('utf-8'))
-        assert response_data['success'] == 1


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-08 15:45  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Dave Page @ 2016-08-08 15:45 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi

I guess you need to test if tablespace_path is omitted, not just empty?

This function test the add tablespace scenario (Check Tablespace Node) ... ERROR

======================================================================
ERROR: setUpClass
(pgadmin.browser.server_groups.servers.tablespaces.tests.test_tbspc_put.TableSpaceUpdateTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py",
line 48, in setUpClass
    cls.server_group, cls.server_ids)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
line 122, in add_table_space
    data = get_tablespace_data(server_connect)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
line 41, in get_tablespace_data
    config_test_data['spc_location'] = server_config['tablespace_path']
KeyError: 'tablespace_path'

======================================================================
ERROR: setUpClass
(pgadmin.browser.server_groups.servers.tablespaces.tests.test_tbspc_delete.TableSpaceDeleteTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py",
line 46, in setUpClass
    cls.server_group, cls.server_ids)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
line 122, in add_table_space
    data = get_tablespace_data(server_connect)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
line 41, in get_tablespace_data
    config_test_data['spc_location'] = server_config['tablespace_path']
KeyError: 'tablespace_path'

======================================================================
ERROR: setUpClass
(pgadmin.browser.server_groups.servers.tablespaces.tests.test_tbspc_get.TablespaceGetTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py",
line 45, in setUpClass
    cls.server_group, cls.server_ids)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
line 122, in add_table_space
    data = get_tablespace_data(server_connect)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
line 41, in get_tablespace_data
    config_test_data['spc_location'] = server_config['tablespace_path']
KeyError: 'tablespace_path'

======================================================================
ERROR: runTest (pgadmin.browser.server_groups.servers.tablespaces.tests.test_tbspc_add.TableSpaceAddTestCase)
This function test the add tablespace scenario (Check Tablespace Node)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py",
line 47, in runTest
    self.server_ids)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
line 122, in add_table_space
    data = get_tablespace_data(server_connect)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
line 41, in get_tablespace_data
    config_test_data['spc_location'] = server_config['tablespace_path']
KeyError: 'tablespace_path'

----------------------------------------------------------------------
Ran 14 tests in 9.326s

FAILED (errors=4)

On Mon, Aug 8, 2016 at 3:07 PM, Navnath Gadakh
<[email protected]> wrote:
> Hi Dave,
>     Please find the updated patch for API unit test cases for Roles and
> Tablespaces nodes
> As we finalized
> Now,
>    1. The user will specify the tablespace path in test_config.json.in
>    2.  If tablespace path not found, skip the test cases for that
> server(Only tablespace test cases)
>    3.  Add the skipped test summary in the test result. (Now it's showing on
> console + in log file, but need to update in a final enhanced test summary
> report. Which is research point we will work on that after finishing all
> nodes API test cases)
>    4.  Removed the test_ prefix from the values in the config files.
>
> Thanks!
>
>
> On Thu, Aug 4, 2016 at 5:55 PM, Dave Page <[email protected]>
> wrote:
>>
>> On Thu, Aug 4, 2016 at 1:02 PM, Navnath Gadakh
>> <[email protected]> wrote:
>> > Hi Dave,
>> >
>> > On Thu, Aug 4, 2016 at 4:04 PM, Dave Page <[email protected]>
>> > wrote:
>> >>
>> >> Hi
>> >>
>> >> On Thu, Aug 4, 2016 at 10:27 AM, Navnath Gadakh
>> >> <[email protected]> wrote:
>> >>
>> >> >> Oh - does the per-server config override the main config? That's
>> >> >> useful. So anything that's in test_advanced_config.py can be
>> >> >> overridden on a per-server basis in test_config.py?
>> >> >
>> >> >     No.
>> >> >     per-server i.e advance config(test_advanced_config.json.in) and
>> >> > main
>> >> > config(test_config.json) both are different files. In main config we
>> >> > just
>> >> > mention the server’s credentials.(We can also mention per server
>> >> > credentails) and in test_advanced_config.json.in(here we say
>> >> > per-server
>> >> > config)
>> >> > we mention the advanced configurations i.e. test data for each node.
>> >>
>> >> OK.
>> >>
>> >> >     So, let's summarize the discussion:
>> >> >     - Let user specify the tablespace path in
>> >> > test_advanced_config.json.in
>> >>
>> >> No - test_config.py. It should be per-server.
>> >
>> >      We don't have a file named 'test_config.py' but we have a server's
>> > credential file named 'test_config.json'.
>> >      So, you are saying the tablespace path to be added in
>> > 'test_config.json'.
>> >      Am I correct?
>>
>> Yeah, sorry. It should be a property of the server configuration.
>>
>>
>> --
>> Dave Page
>> VP, Chief Architect, Tools & Installers
>> EnterpriseDB: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>
>
>
>
> --
> Thanks,
> Navnath Gadakh
> Software Engineer
> EnterpriseDB Corporation
> Mobile: +91 9975389878
>
>



-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers



^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-09 09:19  Navnath Gadakh <[email protected]>
  parent: Dave Page <[email protected]>
  0 siblings, 1 reply; 29+ messages in thread

From: Navnath Gadakh @ 2016-08-09 09:19 UTC (permalink / raw)
  To: Dave Page <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Hi Dave,

On Mon, Aug 8, 2016 at 9:15 PM, Dave Page <[email protected]>
wrote:

> Hi
>
> I guess you need to test if tablespace_path is omitted, not just empty?
>
    Yes, thats right.. Please find the updated patch.

>
> This function test the add tablespace scenario (Check Tablespace Node) ...
> ERROR
>
> ======================================================================
> ERROR: setUpClass
> (pgadmin.browser.server_groups.servers.tablespaces.tests.
> test_tbspc_put.TableSpaceUpdateTestCase)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/tablespaces/tests/test_tbspc_put.py",
> line 48, in setUpClass
>     cls.server_group, cls.server_ids)
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/tablespaces/tests/utils.py",
> line 122, in add_table_space
>     data = get_tablespace_data(server_connect)
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/tablespaces/tests/utils.py",
> line 41, in get_tablespace_data
>     config_test_data['spc_location'] = server_config['tablespace_path']
> KeyError: 'tablespace_path'
>
> ======================================================================
> ERROR: setUpClass
> (pgadmin.browser.server_groups.servers.tablespaces.tests.
> test_tbspc_delete.TableSpaceDeleteTestCase)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/tablespaces/tests/test_tbspc_delete.py",
> line 46, in setUpClass
>     cls.server_group, cls.server_ids)
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/tablespaces/tests/utils.py",
> line 122, in add_table_space
>     data = get_tablespace_data(server_connect)
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/tablespaces/tests/utils.py",
> line 41, in get_tablespace_data
>     config_test_data['spc_location'] = server_config['tablespace_path']
> KeyError: 'tablespace_path'
>
> ======================================================================
> ERROR: setUpClass
> (pgadmin.browser.server_groups.servers.tablespaces.tests.
> test_tbspc_get.TablespaceGetTestCase)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/tablespaces/tests/test_tbspc_get.py",
> line 45, in setUpClass
>     cls.server_group, cls.server_ids)
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/tablespaces/tests/utils.py",
> line 122, in add_table_space
>     data = get_tablespace_data(server_connect)
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/tablespaces/tests/utils.py",
> line 41, in get_tablespace_data
>     config_test_data['spc_location'] = server_config['tablespace_path']
> KeyError: 'tablespace_path'
>
> ======================================================================
> ERROR: runTest (pgadmin.browser.server_groups.servers.tablespaces.tests.
> test_tbspc_add.TableSpaceAddTestCase)
> This function test the add tablespace scenario (Check Tablespace Node)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/tablespaces/tests/test_tbspc_add.py",
> line 47, in runTest
>     self.server_ids)
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/tablespaces/tests/utils.py",
> line 122, in add_table_space
>     data = get_tablespace_data(server_connect)
>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups
> /servers/tablespaces/tests/utils.py",
> line 41, in get_tablespace_data
>     config_test_data['spc_location'] = server_config['tablespace_path']
> KeyError: 'tablespace_path'
>
> ----------------------------------------------------------------------
> Ran 14 tests in 9.326s
>
> FAILED (errors=4)
>
> On Mon, Aug 8, 2016 at 3:07 PM, Navnath Gadakh
> <[email protected]> wrote:
> > Hi Dave,
> >     Please find the updated patch for API unit test cases for Roles and
> > Tablespaces nodes
> > As we finalized
> > Now,
> >    1. The user will specify the tablespace path in test_config.json.in
> >    2.  If tablespace path not found, skip the test cases for that
> > server(Only tablespace test cases)
> >    3.  Add the skipped test summary in the test result. (Now it's
> showing on
> > console + in log file, but need to update in a final enhanced test
> summary
> > report. Which is research point we will work on that after finishing all
> > nodes API test cases)
> >    4.  Removed the test_ prefix from the values in the config files.
> >
> > Thanks!
> >
> >
> > On Thu, Aug 4, 2016 at 5:55 PM, Dave Page <[email protected]>
> > wrote:
> >>
> >> On Thu, Aug 4, 2016 at 1:02 PM, Navnath Gadakh
> >> <[email protected]> wrote:
> >> > Hi Dave,
> >> >
> >> > On Thu, Aug 4, 2016 at 4:04 PM, Dave Page <[email protected]
> >
> >> > wrote:
> >> >>
> >> >> Hi
> >> >>
> >> >> On Thu, Aug 4, 2016 at 10:27 AM, Navnath Gadakh
> >> >> <[email protected]> wrote:
> >> >>
> >> >> >> Oh - does the per-server config override the main config? That's
> >> >> >> useful. So anything that's in test_advanced_config.py can be
> >> >> >> overridden on a per-server basis in test_config.py?
> >> >> >
> >> >> >     No.
> >> >> >     per-server i.e advance config(test_advanced_config.json.in)
> and
> >> >> > main
> >> >> > config(test_config.json) both are different files. In main config
> we
> >> >> > just
> >> >> > mention the server’s credentials.(We can also mention per server
> >> >> > credentails) and in test_advanced_config.json.in(here we say
> >> >> > per-server
> >> >> > config)
> >> >> > we mention the advanced configurations i.e. test data for each
> node.
> >> >>
> >> >> OK.
> >> >>
> >> >> >     So, let's summarize the discussion:
> >> >> >     - Let user specify the tablespace path in
> >> >> > test_advanced_config.json.in
> >> >>
> >> >> No - test_config.py. It should be per-server.
> >> >
> >> >      We don't have a file named 'test_config.py' but we have a
> server's
> >> > credential file named 'test_config.json'.
> >> >      So, you are saying the tablespace path to be added in
> >> > 'test_config.json'.
> >> >      Am I correct?
> >>
> >> Yeah, sorry. It should be a property of the server configuration.
> >>
> >>
> >> --
> >> Dave Page
> >> VP, Chief Architect, Tools & Installers
> >> EnterpriseDB: http://www.enterprisedb.com
> >> The Enterprise PostgreSQL Company
> >>
> >> Blog: http://pgsnake.blogspot.com
> >> Twitter: @pgsnake
> >
> >
> >
> >
> > --
> > Thanks,
> > Navnath Gadakh
> > Software Engineer
> > EnterpriseDB Corporation
> > Mobile: +91 9975389878
> >
> >
>
>
>
> --
> Dave Page
> VP, Chief Architect, Tools & Installers
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>



-- 
Thanks,
Navnath Gadakh
Software Engineer
EnterpriseDB Corporation
Mobile: +91 9975389878


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [application/octet-stream] pgadmin_unittest_roles_tablespaces.patch (105.2K, 3-pgadmin_unittest_roles_tablespaces.patch)
  download | inline diff:
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
index 85dcc6c..490e7d9 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_add.py
@@ -7,10 +7,11 @@
 #
 # ##################################################################
 
-import json
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as database_utils
 
 
 class DatabaseAddTestCase(BaseTestGenerator):
@@ -24,7 +25,8 @@ class DatabaseAddTestCase(BaseTestGenerator):
         ('Check Databases Node URL', dict(url='/browser/database/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function used to add the sever
 
@@ -32,27 +34,23 @@ class DatabaseAddTestCase(BaseTestGenerator):
         """
 
         # Add the server
-        utils.add_server(self.tester)
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the database!!!")
 
     def runTest(self):
         """ This function will add database under 1st server of tree node. """
 
-        server_connect_response, server_group, server_ids = \
-            utils.connect_server(self.tester)
-
-        for server_connect, server_id in zip(server_connect_response,
-                                             server_ids):
-            if server_connect['data']['connected']:
-                data = utils.get_db_data(server_connect)
-                db_response = self.tester.post(self.url + str(server_group) +
-                                               "/" + server_id + "/",
-                                               data=json.dumps(data),
-                                               content_type='html/json')
-                self.assertTrue(db_response.status_code, 200)
-                response_data = json.loads(db_response.data.decode('utf-8'))
-                utils.write_db_parent_id(response_data)
+        database_utils.add_database(self.tester, self.server_connect_response,
+                                    self.server_ids)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the added database, added server and the
         'parent_id.pkl' file which is created in setup()
@@ -60,6 +58,6 @@ class DatabaseAddTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_database(self.tester)
-        utils.delete_server(self.tester)
+        database_utils.delete_database(cls.tester)
+        server_utils.delete_server(cls.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
index 6830b5a..756a689 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_delete.py
@@ -7,12 +7,10 @@
 #
 # ##################################################################
 
-import json
-
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import config_data
-from regression.test_utils import get_ids
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as database_utils
 
 
 class DatabaseDeleteTestCase(BaseTestGenerator):
@@ -23,43 +21,38 @@ class DatabaseDeleteTestCase(BaseTestGenerator):
         ('Check Databases Node URL', dict(url='/browser/database/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function perform the three tasks
          1. Add the test server
          2. Connect to server
+         3. Add the databases
 
         :return: None
         """
 
         # Firstly, add the server
-        utils.add_server(self.tester)
-        # Secondly, connect to server/database
-        utils.connect_server(self.tester)
+        server_utils.add_server(cls.tester)
 
-    def runTest(self):
-        """ This function will delete the database."""
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
 
-        srv_grp = config_data['test_server_group']
-        all_id = get_ids()
-        server_ids = all_id["sid"]
-        db_ids_dict = all_id["did"][0]
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the database!!!")
 
-        for server_id in server_ids:
-            db_id = db_ids_dict[int(server_id)]
-            db_con = utils.verify_database(self.tester, srv_grp, server_id,
-                                           db_id)
-            if len(db_con) == 0:
-                raise Exception("No database(s) to delete for server id %s"
-                                % server_id)
-            response = self.tester.delete(self.url + str(srv_grp) + '/' +
-                                          str(server_id) + '/' + str(db_id),
-                                          follow_redirects=True)
+        # Add database
+        database_utils.add_database(cls.tester, cls.server_connect_response,
+                                    cls.server_ids)
+
+    def runTest(self):
+        """ This function will delete the database."""
 
-            response_data = json.loads(response.data.decode('utf-8'))
-            self.assertTrue(response_data['success'], 1)
+        database_utils.delete_database(self.tester)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the added server and the 'parent_id.pkl' file
         which is created in setup() function.
@@ -67,5 +60,5 @@ class DatabaseDeleteTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_server(self.tester)
+        server_utils.delete_server(cls.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
index 7350f72..739dff8 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_get.py
@@ -11,6 +11,8 @@ from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
 from regression.test_setup import config_data
 from regression.test_utils import get_ids
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as database_utils
 
 
 class DatabasesGetTestCase(BaseTestGenerator):
@@ -20,22 +22,33 @@ class DatabasesGetTestCase(BaseTestGenerator):
 
     scenarios = [
         # Fetching default URL for database node.
-        ('Check Databases Node URL', dict(url='/browser/database/obj/'))
+        ('Check Dat abases Node URL', dict(url='/browser/database/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function perform the three tasks
          1. Add the test server
          2. Connect to server
+         3. Add the databases
 
         :return: None
         """
 
         # Firstly, add the server
-        utils.add_server(self.tester)
-        # Secondly, connect to server/database
-        utils.connect_server(self.tester)
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the database!!!")
+
+        # Add database
+        database_utils.add_database(cls.tester, cls.server_connect_response,
+                                    cls.server_ids)
 
     def runTest(self):
         """ This function will fetch added database. """
@@ -44,19 +57,21 @@ class DatabasesGetTestCase(BaseTestGenerator):
         server_ids = all_id["sid"]
 
         db_ids_dict = all_id["did"][0]
-        srv_grp = config_data['test_server_group']
+        srv_grp = config_data['server_group']
 
         for server_id in server_ids:
             db_id = db_ids_dict[int(server_id)]
-            db_con = utils.verify_database(self.tester, srv_grp, server_id,
-                                           db_id)
+            db_con = database_utils.verify_database(self.tester, srv_grp,
+                                                    server_id,
+                                                    db_id)
             if db_con["info"] == "Database connected.":
                 response = self.tester.get(
                     self.url + str(srv_grp) + '/' + str(server_id) + '/' +
                     str(db_id), follow_redirects=True)
                 self.assertEquals(response.status_code, 200)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the added database, added server
         and the 'parent_id.pkl' file which is created in setup() function.
@@ -64,6 +79,6 @@ class DatabasesGetTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_database(self.tester)
-        utils.delete_server(self.tester)
+        database_utils.delete_database(cls.tester)
+        server_utils.delete_server(cls.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
index 4615d34..c32e3ca 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/test_db_put.py
@@ -11,8 +11,10 @@ import json
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import config_data, advanced_config_data
+from regression.test_setup import advanced_config_data
 from regression.test_utils import get_ids
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as database_utils
 
 
 class DatabasesUpdateTestCase(BaseTestGenerator):
@@ -25,44 +27,58 @@ class DatabasesUpdateTestCase(BaseTestGenerator):
         ('Check Databases Node', dict(url='/browser/database/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function perform the three tasks
          1. Add the test server
          2. Connect to server
+         3. Add the databases
 
         :return: None
         """
 
         # Firstly, add the server
-        utils.add_server(self.tester)
-        # Secondly, connect to server/database
-        utils.connect_server(self.tester)
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the database!!!")
+
+        # Add database
+        database_utils.add_database(cls.tester, cls.server_connect_response,
+                                    cls.server_ids)
 
     def runTest(self):
         """ This function will update the comments field of database."""
 
-        srv_grp = config_data['test_server_group']
         all_id = get_ids()
         server_ids = all_id["sid"]
         db_ids_dict = all_id["did"][0]
 
         for server_id in server_ids:
             db_id = db_ids_dict[int(server_id)]
-            db_con = utils.verify_database(self.tester, srv_grp, server_id,
-                                           db_id)
+            db_con = database_utils.verify_database(self.tester,
+                                                    utils.SERVER_GROUP,
+                                                    server_id,
+                                                    db_id)
             if db_con["info"] == "Database connected.":
                 data = {
-                    "comments": advanced_config_data["test_db_update_data"][0]
-                    ["test_comment"],
+                    "comments": advanced_config_data["db_update_data"][0]
+                    ["comment"],
                     "id": db_id
                 }
                 put_response = self.tester.put(
-                    self.url + str(srv_grp) + '/' + str(server_id) + '/' +
+                    self.url + str(utils.SERVER_GROUP) + '/' + str(
+                        server_id) + '/' +
                     str(db_id), data=json.dumps(data), follow_redirects=True)
                 self.assertEquals(put_response.status_code, 200)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(self):
         """
         This function deletes the added server and 'parent_id.pkl' file
         which is created in setup() function.
@@ -70,5 +86,6 @@ class DatabasesUpdateTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_server(self.tester)
+        database_utils.delete_database(self.tester)
+        server_utils.delete_server(self.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/databases/tests/utils.py b/web/pgadmin/browser/server_groups/servers/databases/tests/utils.py
new file mode 100644
index 0000000..fcffaf4
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/tests/utils.py
@@ -0,0 +1,176 @@
+# ##########################################################################
+#
+# #pgAdmin 4 - PostgreSQL Tools
+#
+# #Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# #This software is released under the PostgreSQL Licence
+#
+# ##########################################################################
+
+import json
+import os
+import pickle
+import uuid
+
+from regression.test_setup import pickle_path, config_data, advanced_config_data
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from regression import test_utils as utils
+
+
+DATABASE_URL = '/browser/database/obj/'
+DATABASE_CONNECT_URL = 'browser/database/connect/'
+
+
+def get_db_data(server_connect_data):
+    """
+    This function is used to get advance config test data for appropriate
+    server
+
+    :param server_connect_data: list of server details
+    :return data: database details
+    :rtype: dict
+    """
+
+    adv_config_data = None
+    data = None
+    db_user = server_connect_data['data']['user']['name']
+
+    # Get the config data of appropriate db user
+    for config_test_data in advanced_config_data['add_database_data']:
+        if db_user == config_test_data['owner']:
+            adv_config_data = config_test_data
+
+    if adv_config_data is not None:
+        data = {
+            "datacl": adv_config_data['privileges_acl'],
+            "datconnlimit": adv_config_data['conn_limit'],
+            "datowner": adv_config_data['owner'],
+            "deffuncacl": adv_config_data['fun_acl'],
+            "defseqacl": adv_config_data['seq_acl'],
+            "deftblacl": adv_config_data['tbl_acl'],
+            "deftypeacl": adv_config_data['type_acl'],
+            "encoding": adv_config_data['encoding'],
+            "name": str(uuid.uuid4())[1:8],
+            "privileges": adv_config_data['privileges'],
+            "securities": adv_config_data['securities'],
+            "variables": adv_config_data['variables']
+        }
+    return data
+
+
+def write_db_id(response_data):
+    """
+    This function writes the server and database related data like server
+    name, server id , database name, database id etc.
+
+    :param response_data: server and databases details
+    :type response_data: dict
+    :return: None
+    """
+
+    db_id = response_data['node']['_id']
+    server_id = response_data['node']['_pid']
+    pickle_id_dict = utils.get_pickle_id_dict()
+    if os.path.isfile(pickle_path):
+        existing_server_id = open(pickle_path, 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+    if 'did' in pickle_id_dict:
+        if pickle_id_dict['did']:
+            # Add the db_id as value in dict
+            pickle_id_dict["did"][0].update({server_id: db_id})
+        else:
+            # Create new dict with server_id and db_id
+            pickle_id_dict["did"].append({server_id: db_id})
+    db_output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, db_output)
+    db_output.close()
+
+
+def add_database(tester, server_connect_response, server_ids):
+    """
+    This function add the database into servers
+
+    :param tester: flask test client
+    :type tester: flask test object
+    :param server_connect_response: server response
+    :type server_connect_response: dict
+    :param server_ids: server ids
+    :type server_ids: list
+    :return: None
+    """
+
+    for server_connect, server_id in zip(server_connect_response, server_ids):
+        if server_connect['data']['connected']:
+            data = get_db_data(server_connect)
+            db_response = tester.post(DATABASE_URL + str(utils.SERVER_GROUP) +
+                                           "/" + server_id + "/",
+                                           data=json.dumps(data),
+                                           content_type='html/json')
+            assert db_response.status_code == 200
+            response_data = json.loads(db_response.data.decode('utf-8'))
+            write_db_id(response_data)
+
+
+def verify_database(tester, server_group, server_id, db_id):
+    """
+    This function verifies that database is exists and whether it connect
+    successfully or not
+
+    :param tester: test client
+    :type tester: flask test client object
+    :param server_group: server group id
+    :type server_group: int
+    :param server_id: server id
+    :type server_id: str
+    :param db_id: database id
+    :type db_id: str
+    :return: temp_db_con
+    :rtype: list
+    """
+
+    # Verify servers
+    server_utils.verify_server(tester,server_group,server_id)
+
+    # Connect to database
+    con_response = tester.post('{0}{1}/{2}/{3}'.format(
+        DATABASE_CONNECT_URL, server_group, server_id, db_id),
+        follow_redirects=True)
+    temp_db_con = json.loads(con_response.data.decode('utf-8'))
+
+    return temp_db_con
+
+
+def delete_database(tester):
+    """
+    This function used to delete the added databases
+
+    :param tester: test client object
+    :return: None
+    """
+
+    server_ids = None
+    db_ids_dict = None
+
+    all_id = utils.get_ids()
+    if "sid" and "did" in all_id.keys():
+        server_ids = all_id["sid"]
+        if all_id['did']:
+            db_ids_dict = all_id['did'][0]
+    else:
+        raise Exception("Keys are not found in pickle dict: {}".format(["sid", "did"]))
+
+    if server_ids and db_ids_dict is not None:
+        for server_id in server_ids:
+            server_response = server_utils.verify_server(tester, utils.SERVER_GROUP, server_id)
+            if server_response["data"]["connected"]:
+                db_id = db_ids_dict[int(server_id)]
+                response = tester.delete(DATABASE_URL + str(utils.SERVER_GROUP) + '/' +
+                                         str(server_id) + '/' + str(db_id),
+                                         follow_redirects=True)
+                assert response.status_code == 200
+                response_data = json.loads(response.data.decode('utf-8'))
+                assert response_data['success'] == 1
+    else:
+        raise Exception("No servers/databases found.")
+
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/roles/tests/__init__.py
new file mode 100644
index 0000000..4a11bf8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/__init__.py
@@ -0,0 +1,16 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class RoleGeneratorTestCase(BaseTestGenerator):
+
+    def runTest(self):
+        return
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_add.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_add.py
new file mode 100644
index 0000000..9d8f949
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_add.py
@@ -0,0 +1,55 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as roles_utils
+
+
+class LoginRoleAddTestCase(BaseTestGenerator):
+    """This class has add role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the roles!!!")
+
+    def runTest(self):
+        """This function test the add role scenario"""
+
+        roles_utils.add_role(self.tester, self.server_connect_response,
+                             self.server_group, self.server_ids)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the role,server and parent id file"""
+
+        roles_utils.delete_role(cls.tester)
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
+
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_delete.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_delete.py
new file mode 100644
index 0000000..f3204cd
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_delete.py
@@ -0,0 +1,58 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as roles_utils
+
+
+class LoginRoleDeleteTestCase(BaseTestGenerator):
+    """This class has delete role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever and roles
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the roles!!!")
+
+        # Add the role
+        roles_utils.add_role(cls.tester, cls.server_connect_response,
+                             cls.server_group, cls.server_ids)
+
+    def runTest(self):
+        """This function tests the delete role scenario"""
+
+        roles_utils.delete_role(self.tester)
+
+    @classmethod
+    def tearDownClass(self):
+        """This function deletes the role,server and parent id file"""
+
+        server_utils.delete_server(self.tester)
+        utils.delete_parent_id_file()
+
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_get.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_get.py
new file mode 100644
index 0000000..4187fca
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_get.py
@@ -0,0 +1,67 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as roles_utils
+
+
+class LoginRoleGetTestCase(BaseTestGenerator):
+    """This class tests the get role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever and roles
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to get the roles!!!")
+
+        # Add the role
+        roles_utils.add_role(cls.tester, cls.server_connect_response,
+                             cls.server_group, cls.server_ids)
+
+    def runTest(self):
+        """This function test the get role scenario"""
+
+        all_id = utils.get_ids()
+        server_ids = all_id["sid"]
+        role_ids_dict = all_id["lrid"][0]
+
+        for server_id in server_ids:
+            role_id = role_ids_dict[int(server_id)]
+            response = self.tester.get(
+                self.url + str(utils.SERVER_GROUP) + '/' +
+                str(server_id) + '/' + str(role_id),
+                follow_redirects=True)
+            self.assertEquals(response.status_code, 200)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the role,server and parent id file"""
+
+        roles_utils.delete_role(cls.tester)
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_put.py b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_put.py
new file mode 100644
index 0000000..f8c353e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/test_role_put.py
@@ -0,0 +1,84 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from regression.test_setup import advanced_config_data
+from . import utils as roles_utils
+
+
+class LoginRolePutTestCase(BaseTestGenerator):
+    """This class has update role scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Role Node', dict(url='/browser/role/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever and roles
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to get the roles!!!")
+
+        # Add the role
+        roles_utils.add_role(cls.tester, cls.server_connect_response,
+                             cls.server_group, cls.server_ids)
+
+    def runTest(self):
+        """This function tests the update role data scenario"""
+
+        all_id = utils.get_ids()
+        server_ids = all_id["sid"]
+        role_ids_dict = all_id["lrid"][0]
+
+        for server_id in server_ids:
+            role_id = role_ids_dict[int(server_id)]
+            role_response = roles_utils.verify_role(self.tester,
+                                                    utils.SERVER_GROUP,
+                                                    server_id,
+                                                    role_id)
+            if len(role_response) == 0:
+                raise Exception("No roles(s) to update!!!")
+
+            data = {
+                "description": advanced_config_data["lr_update_data"]
+                ["comment"],
+                "lrid": role_id
+            }
+            put_response = self.tester.put(
+                self.url + str(utils.SERVER_GROUP) + '/' +
+                str(server_id) + '/' + str(role_id),
+                data=json.dumps(data),
+                follow_redirects=True)
+
+            self.assertEquals(put_response.status_code, 200)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the role,server and parent id file"""
+
+        roles_utils.delete_role(cls.tester)
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/utils.py b/web/pgadmin/browser/server_groups/servers/roles/tests/utils.py
new file mode 100644
index 0000000..85e0990
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/utils.py
@@ -0,0 +1,187 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+import os
+import pickle
+import uuid
+
+from regression.test_setup import pickle_path, config_data, advanced_config_data
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from regression import test_utils as utils
+
+
+ROLE_URL = '/browser/role/obj/'
+
+
+def verify_role(tester, server_group, server_id, role_id):
+    """
+    This function calls the GET API for role to verify
+
+    :param tester: test client
+    :type tester: flask test client object
+    :param server_group: server group id
+    :type server_group: int
+    :param server_id: server id
+    :type server_id: str
+    :param role_id: role id
+    :type role_id: int
+    :return: dict/None
+    """
+
+    srv_connect = server_utils.verify_server(tester, server_group, server_id)
+    if srv_connect['data']['connected']:
+        response = tester.get(
+            '{0}{1}/{2}/{3}'.format(ROLE_URL, server_group, server_id,
+                                    role_id),
+            content_type='html/json')
+        temp_response = json.loads(response.data.decode('utf-8'))
+        return temp_response
+    else:
+        return None
+
+
+def test_getrole(tester):
+    if not tester:
+        return None
+
+    all_id = utils.get_ids()
+
+    server_ids = all_id["sid"]
+    role_ids_dict = all_id["lrid"][0]
+    server_group = config_data['server_group']
+
+    role_response_data = []
+    for server_id in server_ids:
+        role_id = role_ids_dict[int(server_id)]
+        role_response_data.append(
+            verify_role(tester, server_group, server_id, role_id))
+    return role_response_data
+
+
+def get_role_data():
+    """This function returns the role data from config file"""
+
+    data = {
+        "rolcanlogin": advanced_config_data['lr_credentials']
+        ['can_login'],
+        "rolconnlimit": advanced_config_data['lr_credentials']
+        ['conn_limit'],
+        "rolcreaterole": advanced_config_data['lr_credentials']
+        ['create_role'],
+        "rolinherit": advanced_config_data['lr_credentials']
+        ['role_inherit'],
+        "rolmembership": advanced_config_data['lr_credentials']
+        ['role_membership'],
+        "rolname": str(uuid.uuid4())[1:8],
+        "rolpassword": advanced_config_data['lr_credentials']
+        ['lr_password'],
+        "rolvaliduntil": advanced_config_data['lr_credentials']
+        ['lr_validity'],
+        "seclabels": advanced_config_data['lr_credentials']
+        ['sec_lable'],
+        "variables": advanced_config_data['lr_credentials']
+        ['variable']
+    }
+    return data
+
+
+def add_role(tester, server_connect_response, server_group, server_ids):
+    """
+    This function is used to add the roles to server
+
+    :param tester: flask test client
+    :type tester: flask test client object
+    :param server_connect_response: server connect API response
+    :type server_connect_response: dict
+    :param server_group: server group
+    :type server_group: int
+    :param server_ids: list of server id
+    :type server_ids: list
+    :return: None
+    """
+
+    for server_connect, server_id in zip(server_connect_response,
+                                         server_ids):
+        if server_connect['data']['connected']:
+            data = get_role_data()
+            response = tester.post(ROLE_URL + str(server_group) + '/'
+                                   + server_id + '/', data=json.dumps(data),
+                                   content_type='html/json')
+            assert response.status_code == 200
+            response_data = json.loads(response.data.decode('utf-8'))
+            write_role_id(response_data)
+
+
+def write_role_id(response_data):
+    """
+
+    :param response_data:
+    :return:
+    """
+
+    lr_id = response_data['node']['_id']
+    server_id = response_data['node']['_pid']
+    pickle_id_dict = utils.get_pickle_id_dict()
+    # TODO: modify logic to write in file / file exists or create new check
+    # old file
+    if os.path.isfile(pickle_path):
+        existing_server_id = open(pickle_path, 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+    if 'lrid' in pickle_id_dict:
+        if pickle_id_dict['lrid']:
+            # Add the db_id as value in dict
+            pickle_id_dict["lrid"][0].update({server_id: lr_id})
+        else:
+            # Create new dict with server_id and db_id
+            pickle_id_dict["lrid"].append({server_id: lr_id})
+    db_output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, db_output)
+    db_output.close()
+
+
+def delete_role(tester):
+    """
+    This function use to delete the existing roles in the servers
+
+    :param tester: flask test client
+    :type tester: flask test object
+    :return: None
+    """
+
+    server_ids = None
+    role_ids_dict = None
+
+    all_id = utils.get_ids()
+    if "sid" and "lrid" in all_id.keys():
+        server_ids = all_id["sid"]
+        if all_id['lrid']:
+            role_ids_dict = all_id['lrid'][0]
+    else:
+        raise Exception("Keys are not found: {}".format(["sid", "lrid"]))
+
+    if server_ids and role_ids_dict is not None:
+        for server_id in server_ids:
+            server_response = server_utils.verify_server(tester,
+                                                         utils.SERVER_GROUP,
+                                                         server_id)
+            if server_response["data"]["connected"]:
+                role_id = role_ids_dict[int(server_id)]
+                response = tester.delete(
+                    ROLE_URL + str(utils.SERVER_GROUP) + '/' +
+                    str(server_id) + '/' + str(role_id),
+                    follow_redirects=True)
+                assert response.status_code == 200
+                response_data = json.loads(response.data.decode('utf-8'))
+                assert response_data['success'] == 1
+    else:
+        raise Exception("No servers/roles found.")
+
+
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/__init__.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/__init__.py
new file mode 100644
index 0000000..3302027
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/__init__.py
@@ -0,0 +1,16 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+
+
+class TblspaceGeneratorTestCase(BaseTestGenerator):
+
+    def runTest(self):
+        return
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py
new file mode 100644
index 0000000..caa6966
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py
@@ -0,0 +1,55 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as tablespace_utils
+
+
+class TableSpaceAddTestCase(BaseTestGenerator):
+    """This class will add tablespace node under server"""
+
+    scenarios = [
+        # Fetching default URL for tablespace node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the roles!!!")
+
+    def runTest(self):
+        """This function test the add tablespace scenario"""
+
+        tablespace_status = tablespace_utils.add_table_space(
+            self.tester, self.server_connect_response, self.server_group,
+            self.server_ids)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the tablespaces,server and parent_id file"""
+
+        tablespace_utils.delete_table_space(cls.tester)
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py
new file mode 100644
index 0000000..f280ee6
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py
@@ -0,0 +1,58 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as tablespace_utils
+
+
+class TableSpaceDeleteTestCase(BaseTestGenerator):
+    """This class has delete table space scenario"""
+
+    scenarios = [
+        # Fetching default URL for tablespace node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the roles!!!")
+
+        # Add tablespace
+        tablespace_utils.add_table_space(cls.tester,
+                                         cls.server_connect_response,
+                                         cls.server_group, cls.server_ids)
+
+    def runTest(self):
+        """This function tests the delete table space scenario"""
+
+        tablespace_utils.delete_table_space(self.tester)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the server and parent id file"""
+
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py
new file mode 100644
index 0000000..b26d71d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py
@@ -0,0 +1,78 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from . import utils as tablespace_utils
+
+
+class TablespaceGetTestCase(BaseTestGenerator):
+    """This class tests the get table space scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the roles!!!")
+
+        # Add tablespace
+        tablespace_utils.add_table_space(cls.tester,
+                                         cls.server_connect_response,
+                                         cls.server_group, cls.server_ids)
+
+    def runTest(self):
+        """This function test the get table space scenario"""
+
+        tablespace_ids_dict = None
+        all_id = utils.get_ids()
+        server_ids = all_id["sid"]
+        if "tsid" in all_id and all_id["tsid"]:
+            tablespace_ids_dict = all_id["tsid"][0]
+
+        if tablespace_ids_dict:
+            for server_id in server_ids:
+                tablespace_id = tablespace_ids_dict[int(server_id)]
+                server_response = server_utils.verify_server(self.tester,
+                                                             utils.SERVER_GROUP,
+                                                             server_id)
+                if server_response['data']['connected']:
+                    tablespace_utils.verify_table_space(
+                        self.tester, utils.SERVER_GROUP, server_id, tablespace_id)
+                    response = self.tester.get(
+                        self.url + str(utils.SERVER_GROUP) + '/' +
+                        str(server_id) + '/' + str(
+                            tablespace_id),
+                        follow_redirects=True)
+                    self.assertEquals(response.status_code, 200)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the tablespaces,server and parent id file"""
+
+        tablespace_utils.delete_table_space(cls.tester)
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py
new file mode 100644
index 0000000..22257f9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py
@@ -0,0 +1,90 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+import json
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import test_utils as utils
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from test_setup import advanced_config_data
+from . import utils as tablespace_utils
+
+
+class TableSpaceUpdateTestCase(BaseTestGenerator):
+    """This class has update tablespace scenario"""
+
+    scenarios = [
+        # Fetching default URL for roles node.
+        ('Check Tablespace Node', dict(url='/browser/tablespace/obj/'))
+    ]
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        This function used to add the sever
+
+        :return: None
+        """
+
+        # Add the server
+        server_utils.add_server(cls.tester)
+
+        # Connect to server
+        cls.server_connect_response, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect_response) == 0:
+            raise Exception("No Server(s) connected to add the roles!!!")
+
+        # Add tablespace
+        tablespace_utils.add_table_space(cls.tester,
+                                         cls.server_connect_response,
+                                         cls.server_group, cls.server_ids)
+
+    def runTest(self):
+        """This function tests the update tablespace data scenario"""
+
+        tablespace_ids_dict = None
+        all_id = utils.get_ids()
+        server_ids = all_id["sid"]
+        if "tsid" in all_id and all_id["tsid"]:
+            tablespace_ids_dict = all_id["tsid"][0]
+
+        if tablespace_ids_dict:
+            for server_id in server_ids:
+                tablespace_id = tablespace_ids_dict[int(server_id)]
+                tablespace_response = tablespace_utils.verify_table_space(
+                    self.tester,
+                    utils.SERVER_GROUP, server_id,
+                    tablespace_id)
+                if len(tablespace_response) == 0:
+                    raise Exception("No tablespace(s) to update!!!")
+
+                data = {
+                    "description": advanced_config_data["tbspc_update_data"]
+                    ["comment"],
+                    "table_space_id": tablespace_id
+                }
+
+                put_response = self.tester.put(
+                    self.url + str(utils.SERVER_GROUP) + '/' +
+                    str(server_id) + '/' + str(
+                        tablespace_id),
+                    data=json.dumps(data),
+                    follow_redirects=True)
+
+                self.assertEquals(put_response.status_code, 200)
+
+    @classmethod
+    def tearDownClass(cls):
+        """This function deletes the tablespaces,server and parent id file"""
+
+        tablespace_utils.delete_table_space(cls.tester)
+        server_utils.delete_server(cls.tester)
+        utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py
new file mode 100644
index 0000000..e871e60
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py
@@ -0,0 +1,195 @@
+# #################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+# ##################################################################
+
+from __future__ import print_function
+
+import json
+import os
+import pickle
+import uuid
+import sys
+
+from regression.test_setup import pickle_path, config_data, \
+    advanced_config_data
+from pgadmin.browser.server_groups.servers.tests import utils as server_utils
+from regression import test_utils as utils
+
+TABLE_SPACE_URL = '/browser/tablespace/obj/'
+
+
+# Tablespace utility
+def get_tablespace_data(server_connect):
+    """This function returns the tablespace data from config file"""
+
+    adv_config_data = None
+    data = None
+    db_user = server_connect['data']['user']['name']
+    server_config_data = config_data['server_credentials']
+
+    # Get the config data of appropriate db user
+    for config_test_data in advanced_config_data['tablespc_credentials']:
+        if db_user == config_test_data['spc_user']:
+            # Add the tablespace path from server config
+            server_config = (item for item in server_config_data if
+                             item["db_username"] == db_user).next()
+            if "tablespace_path" in server_config:
+                config_test_data['spc_location'] = server_config['tablespace_path']
+                adv_config_data = config_test_data
+            else:
+                config_test_data['spc_location'] = None
+
+    if adv_config_data is not None:
+        data = {
+            "name": str(uuid.uuid4())[1:8],
+            "seclabels": adv_config_data["spc_seclable"],
+            "spcacl": adv_config_data["spc_acl"],
+            "spclocation": adv_config_data["spc_location"],
+            "spcoptions": adv_config_data["spc_opts"],
+            "spcuser": adv_config_data["spc_user"]
+        }
+    return data
+
+
+def write_tablespace_id(response_data):
+    """
+    This function write the table space id to parent_id.pkl
+
+    :param response_data: create table space API response data
+    :type response_data: dict
+    :return: None
+    """
+
+    table_space_id = response_data['node']['_id']
+    server_id = response_data['node']['_pid']
+    pickle_id_dict = utils.get_pickle_id_dict()
+    if os.path.isfile(pickle_path):
+        existing_server_id = open(pickle_path, 'rb')
+        tol_server_id = pickle.load(existing_server_id)
+        pickle_id_dict = tol_server_id
+    if 'tsid' in pickle_id_dict:
+        if pickle_id_dict['tsid']:
+            # Add the db_id as value in dict
+            pickle_id_dict["tsid"][0].update(
+                {server_id: table_space_id})
+        else:
+            # Create new dict with server_id and db_id
+            pickle_id_dict["tsid"].append(
+                {server_id: table_space_id})
+    db_output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, db_output)
+    db_output.close()
+
+
+def add_table_space(tester, server_connect_response, server_group, server_ids):
+    """
+    This function is used to add the roles to server
+
+    :param tester: flask test client
+    :type tester: flask test client object
+    :param server_connect_response: server connect API response
+    :type server_connect_response: dict
+    :param server_group: server group
+    :type server_group: int
+    :param server_ids: list of server id
+    :type server_ids: list
+    :return: None
+    """
+
+    total_servers_count = len(server_ids)
+    servers_without_tablespace_path = []
+
+    for server_connect, server_id in zip(server_connect_response,
+                                         server_ids):
+        tablespace_path = server_connect['tablespace_path']
+        # Skip the test case if tablespace_path does not exist
+        if not tablespace_path or tablespace_path is None:
+            file_name = os.path.basename(
+                sys._getframe().f_back.f_code.co_filename)
+            servers_without_tablespace_path.append(server_id)
+            if total_servers_count == len(servers_without_tablespace_path):
+                print("Skipping tablespaces test cases for the  file <{0}>, "
+                      "Tablespace path not found for any of the server : "
+                      "{1}".format(file_name, server_ids), file=sys.stderr)
+                return
+            else:
+                print("Skipping tablespaces test case for the file <{0}>: "
+                      "Tablespace path not found for server : {1}".format(
+                        file_name, server_id), file=sys.stderr)
+                continue
+
+        if server_connect['data']['connected']:
+            data = get_tablespace_data(server_connect)
+            response = tester.post(TABLE_SPACE_URL + str(server_group) + '/'
+                                   + server_id + '/',
+                                   data=json.dumps(data),
+                                   content_type='html/json')
+            assert response.status_code == 200
+            response_data = json.loads(response.data.decode('utf-8'))
+            write_tablespace_id(response_data)
+
+
+def verify_table_space(tester, server_group, server_id, tablespace_id):
+    """
+    This function calls the GET API for role to verify
+
+    :param tester: test client
+    :type tester: flask test client object
+    :param server_group: server group id
+    :type server_group: int
+    :param server_id: server id
+    :type server_id: str
+    :param tablespace_id: table space id
+    :type tablespace_id: int
+    :return: dict/None
+    """
+
+    srv_connect = server_utils.verify_server(tester, server_group, server_id)
+    if srv_connect['data']['connected']:
+        response = tester.get(
+            '{0}{1}/{2}/{3}'.format(TABLE_SPACE_URL, server_group, server_id,
+                                    tablespace_id),
+            content_type='html/json')
+        assert response.status_code == 200
+        temp_response = json.loads(response.data.decode('utf-8'))
+        return temp_response
+    else:
+        return None
+
+
+def delete_table_space(tester):
+    """
+    This function use to delete the existing tablespace in the servers
+
+    :param tester: flask test client
+    :type tester: flask test object
+    :return: None
+    """
+
+    all_id = utils.get_ids()
+    server_ids = all_id["sid"]
+    if "tsid" in all_id and all_id["tsid"]:
+        tablespace_ids_dict = all_id["tsid"][0]
+    else:
+        tablespace_ids_dict = None
+
+    if tablespace_ids_dict is not None:
+        for server_id in server_ids:
+            tablespace_id = tablespace_ids_dict[int(server_id)]
+            role_response = verify_table_space(tester, utils.SERVER_GROUP,
+                                               server_id,
+                                               tablespace_id)
+            if len(role_response) == 0:
+                raise Exception("No tablespace(s) to delete!!!")
+            response = tester.delete(
+                TABLE_SPACE_URL + str(utils.SERVER_GROUP) + '/' +
+                str(server_id) + '/' + str(tablespace_id),
+                follow_redirects=True)
+            assert response.status_code == 200
+            delete_response_data = json.loads(response.data.decode('utf-8'))
+            assert delete_response_data['success'] == 1
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 2b1eb45..7348a47 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
@@ -7,10 +7,9 @@
 #
 # ##########################################################################
 
-import json
-
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
+from . import utils as server_utils
 
 
 class ServersAddTestCase(BaseTestGenerator):
@@ -21,24 +20,17 @@ class ServersAddTestCase(BaseTestGenerator):
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         pass
 
     def runTest(self):
         """ This function will add the server under default server group."""
 
-        server_group, config_data, pickle_id_dict = utils.get_config_data()
-        for server_data in config_data:
-            url = "{0}{1}/".format(self.url, server_group)
-            response = self.tester.post(url, data=json.dumps(server_data),
-                                        content_type='html/json')
-
-            self.assertTrue(response.status_code, 200)
-
-            response_data = json.loads(response.data.decode())
-            utils.write_parent_id(response_data, pickle_id_dict)
+        server_utils.add_server(self.tester)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the added server and the 'parent_id.pkl' file
         which is created in setup() function.
@@ -46,5 +38,5 @@ class ServersAddTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_server(self.tester)
+        server_utils.delete_server(cls.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
index 4fd207b..6431bec 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_delete.py
@@ -7,12 +7,11 @@
 #
 # ##################################################################
 
-import json
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import config_data
-from regression.test_utils import get_ids
+
+from . import utils as server_utils
 
 
 class ServerDeleteTestCase(BaseTestGenerator):
@@ -23,7 +22,8 @@ class ServerDeleteTestCase(BaseTestGenerator):
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function is used to add the server
 
@@ -31,28 +31,16 @@ class ServerDeleteTestCase(BaseTestGenerator):
         """
 
         # Firstly, add the server
-        utils.add_server(self.tester)
+        server_utils.add_server(cls.tester)
 
     def runTest(self):
         """ This function will get all available servers under object browser
         and delete the last server using server id."""
 
-        srv_grp = config_data['test_server_group']
-        all_id = get_ids()
-        server_ids = all_id["sid"]
-
-        url = self.url + str(srv_grp) + "/"
-        if len(server_ids) == 0:
-            raise Exception("No server(s) to delete!!!")
-
-        # Call api to delete the servers
-        for server_id in server_ids:
-            response = self.tester.delete(url + str(server_id))
-            self.assertTrue(response.status_code, 200)
-            response_data = json.loads(response.data.decode())
-            self.assertTrue(response_data['success'], 1)
+        server_utils.delete_server(self.tester)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the 'parent_id.pkl' file which is created in
         setup() function.
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
index ea3c63f..e541247 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_get.py
@@ -9,8 +9,7 @@
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import config_data
-from regression.test_utils import get_ids
+from . import utils as server_utils
 
 
 class ServersGetTestCase(BaseTestGenerator):
@@ -24,28 +23,23 @@ class ServersGetTestCase(BaseTestGenerator):
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function is used to add the server
 
         :return: None
         """
 
-        utils.add_server(self.tester)
+        server_utils.add_server(cls.tester)
 
     def runTest(self):
         """ This function will fetch the added servers to object browser. """
 
-        all_id = get_ids()
-        server_ids = all_id["sid"]
-        srv_grp = config_data['test_server_group']
+        server_utils.get_server(self.tester)
 
-        for server_id in server_ids:
-            url = "{0}{1}/{2}".format(self.url, srv_grp, server_id)
-            response = self.tester.get(url, content_type='html/json')
-            self.assertEquals(response.status_code, 200)
-
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the added server and the 'parent_id.pkl' file
         which is created in setup() function.
@@ -53,5 +47,5 @@ class ServersGetTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_server(self.tester)
+        server_utils.delete_server(cls.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
index 5e810ba..9ac6468 100644
--- a/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
+++ b/web/pgadmin/browser/server_groups/servers/tests/test_server_put.py
@@ -8,10 +8,9 @@
 # ##########################################################################
 
 import json
-
 from pgadmin.utils.route import BaseTestGenerator
 from regression import test_utils as utils
-from regression.test_setup import config_data
+from . import utils as server_utils
 
 
 class ServerUpdateTestCase(BaseTestGenerator):
@@ -22,7 +21,8 @@ class ServerUpdateTestCase(BaseTestGenerator):
         ('Default Server Node url', dict(url='/browser/server/obj/'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         This function perform the four tasks
          1. Add the test server
@@ -33,13 +33,16 @@ class ServerUpdateTestCase(BaseTestGenerator):
         """
 
         # Firstly, add the server
-        utils.add_server(self.tester)
+        server_utils.add_server(cls.tester)
+
         # Get the server
-        utils.get_server(self.tester)
+        server_utils.get_server(cls.tester)
+
         # Connect to server
-        self.server_connect, self.server_group, self.server_ids = \
-            utils.connect_server(self.tester)
-        if len(self.server_connect) == 0:
+        cls.server_connect, cls.server_group, cls.server_ids = \
+            server_utils.connect_server(cls.tester)
+
+        if len(cls.server_connect) == 0:
             raise Exception("No Server(s) connected to update!!!")
 
     def runTest(self):
@@ -48,7 +51,8 @@ class ServerUpdateTestCase(BaseTestGenerator):
         for server_id in self.server_ids:
             data = {
                 "comment":
-                    config_data['test_server_update_data'][0]['test_comment'],
+                    server_utils.config_data['server_update_data'][0][
+                        'comment'],
                 "id": server_id
             }
             put_response = self.tester.put(
@@ -60,7 +64,8 @@ class ServerUpdateTestCase(BaseTestGenerator):
             response_data = json.loads(put_response.data.decode())
             self.assertTrue(response_data['success'], 1)
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         This function deletes the added server and the 'parent_id.pkl' file
         which is created in setup() function.
@@ -68,5 +73,5 @@ class ServerUpdateTestCase(BaseTestGenerator):
         :return: None
         """
 
-        utils.delete_server(self.tester)
+        server_utils.delete_server(cls.tester)
         utils.delete_parent_id_file()
diff --git a/web/pgadmin/browser/server_groups/servers/tests/utils.py b/web/pgadmin/browser/server_groups/servers/tests/utils.py
new file mode 100644
index 0000000..6e3f166
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tests/utils.py
@@ -0,0 +1,160 @@
+# ##########################################################################
+#
+# #pgAdmin 4 - PostgreSQL Tools
+#
+# #Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# #This software is released under the PostgreSQL Licence
+#
+# ##########################################################################
+
+import json
+import os
+import pickle
+
+from regression import test_utils as utils
+from regression.test_setup import pickle_path, config_data
+
+SERVER_URL = '/browser/server/obj/'
+SERVER_CONNECT_URL = 'browser/server/connect/'
+
+
+def write_server_id(response_data, pickle_id_dict):
+    """
+    This function writes the server's details to file parent_id.pkl
+
+    :param response_data: server's data
+    :type response_data: list of dictionary
+    :param pickle_id_dict: contains ids of server,database,tables etc.
+    :type pickle_id_dict: dict
+    :return: None
+    """
+
+    server_id = response_data['node']['_id']
+    if os.path.isfile(pickle_path):
+        existed_server_id = open(pickle_path, 'rb')
+        pickle_id_dict = pickle.load(existed_server_id)
+
+    pickle_id_dict["sid"].append(str(server_id))
+    output = open(pickle_path, 'wb')
+    pickle.dump(pickle_id_dict, output)
+    output.close()
+
+
+def add_server(tester):
+    """
+    This function add the server in the existing server group
+
+    :param tester: test object
+    :type tester: flask test object
+    :return:None
+    """
+
+    server_group, db_data, pickle_id_dict = utils.get_config_data()
+    url = "{0}{1}/".format(SERVER_URL, server_group)
+    for db_detail in db_data:
+        response = tester.post(url, data=json.dumps(db_detail),
+                               content_type='html/json')
+        assert response.status_code == 200
+        response_data = json.loads(response.data.decode('utf-8'))
+        write_server_id(response_data, pickle_id_dict)
+
+
+def get_server(tester):
+    """
+    This function gets the added serer details
+
+    :param tester: test client object
+    :type tester: flask test object
+    :return: response_data
+    :rtype: list
+    """
+
+    all_id = utils.get_ids()
+    server_ids = all_id["sid"]
+    for server_id in server_ids:
+        response = tester.get(SERVER_URL + str(utils.SERVER_GROUP) + '/' +
+                              str(server_id),
+                              follow_redirects=True)
+        assert response.status_code == 200
+
+
+def connect_server(tester):
+    """
+    This function used to connect added server
+
+    :param tester:test client object
+    :type tester: flask test object
+    :param add_db_flag: flag for db add test case
+    :type add_db_flag: bool
+    :return: server_connect, server_group, server_id
+    :rtype: server_connect:dict, server_group:dict, server_id:str
+    """
+
+    server_connect = []
+    servers = []
+    server_config = None
+
+    srv_id = utils.get_ids()
+    server_ids = srv_id["sid"]
+
+    # Connect to all servers
+    for server_id in server_ids:
+        response = tester.post(SERVER_CONNECT_URL + str(utils.SERVER_GROUP) +
+                               '/' + server_id,
+                               data=dict(
+                                   password=config_data
+                                   ['server_credentials'][0]
+                                   ['db_password']),
+                               follow_redirects=True)
+        server_connect_detail = json.loads(response.data.decode('utf-8'))
+        db_user = server_connect_detail['data']['user']['name']
+        server_connect_detail['tablespace_path'] = None
+
+        # Get the server config of appropriate db user
+        for config in config_data['server_credentials']:
+            if db_user == config['db_username']:
+                server_config = config
+
+        if "tablespace_path" in server_config:
+            server_connect_detail['tablespace_path'] = \
+                server_config['tablespace_path']
+
+        server_connect.append(server_connect_detail)
+        servers.append(server_id)
+    return server_connect, utils.SERVER_GROUP, servers
+
+
+def verify_server(tester, server_group, server_id):
+    """This function verifies that server is connecting or not"""
+
+    response = tester.post(
+        '{0}{1}/{2}'.format(SERVER_CONNECT_URL, server_group, server_id),
+        data=dict(password=config_data
+        ['server_credentials'][0]
+        ['db_password']),
+        follow_redirects=True)
+    srv_connect = json.loads(response.data.decode('utf-8'))
+    return srv_connect
+
+
+def delete_server(tester):
+    """
+    This function used to delete the added servers
+
+    :param tester: test client object
+    :return: None
+    """
+
+    all_id = utils.get_ids()
+    server_ids = all_id["sid"]
+    url = SERVER_URL + str(utils.SERVER_GROUP) + "/"
+
+    if len(server_ids) == 0:
+        raise Exception("No server(s) to delete!!!")
+
+    # Call api to delete the servers
+    for server_id in server_ids:
+        response = tester.delete(url + str(server_id))
+        assert response.status_code == 200
+        response_data = json.loads(response.data.decode('utf-8'))
+        assert response_data['success'] == 1
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/tests/test_sg_get.py b/web/pgadmin/browser/server_groups/tests/test_sg_get.py
index 6c164be..5df67c9 100644
--- a/web/pgadmin/browser/server_groups/tests/test_sg_get.py
+++ b/web/pgadmin/browser/server_groups/tests/test_sg_get.py
@@ -26,7 +26,7 @@ class SgNodeTestCase(BaseTestGenerator):
     def runTest(self):
         """This function will check available server groups."""
 
-        server_group_id = config_data['test_server_group']
+        server_group_id = config_data['server_group']
         response = self.tester.get(self.url + str(server_group_id),
                                    content_type='html/json')
         self.assertTrue(response.status_code, 200)
diff --git a/web/pgadmin/browser/tests/test_change_password.py b/web/pgadmin/browser/tests/test_change_password.py
index 2f714a7..5b7c918 100644
--- a/web/pgadmin/browser/tests/test_change_password.py
+++ b/web/pgadmin/browser/tests/test_change_password.py
@@ -8,9 +8,12 @@
 # ##########################################################################
 
 import uuid
+import json
 
 from pgadmin.utils.route import BaseTestGenerator
 from regression.test_setup import config_data
+from regression import test_utils as utils
+from utils import change_password
 
 
 class ChangePasswordTestCase(BaseTestGenerator):
@@ -24,9 +27,9 @@ class ChangePasswordTestCase(BaseTestGenerator):
         # This testcase validates invalid confirmation password
         ('TestCase for Validating Incorrect_New_Password', dict(
             password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password']),
+                      ['login_password']),
             new_password=(config_data['pgAdmin4_login_credentials']
-                          ['test_new_password']),
+                          ['new_password']),
             new_password_confirm=str(uuid.uuid4())[4:8],
             respdata='Passwords do not match')),
 
@@ -34,7 +37,7 @@ class ChangePasswordTestCase(BaseTestGenerator):
         # minimum length
         ('TestCase for Validating New_Password_Less_Than_Min_Length',
          dict(password=(config_data['pgAdmin4_login_credentials']
-                        ['test_login_password']),
+                        ['login_password']),
               new_password=str(uuid.uuid4())[4:8],
               new_password_confirm=str(uuid.uuid4())[4:8],
               respdata='Password must be at least 6 characters')),
@@ -42,7 +45,7 @@ class ChangePasswordTestCase(BaseTestGenerator):
         # This testcase validates if both password fields are left blank
         ('TestCase for Validating Empty_New_Password', dict(
             password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password']),
+                      ['login_password']),
             new_password='', new_password_confirm='',
             respdata='Password not provided')),
 
@@ -50,57 +53,66 @@ class ChangePasswordTestCase(BaseTestGenerator):
         ('TestCase for Validating Incorrect_Current_Password', dict(
             password=str(uuid.uuid4())[4:8],
             new_password=(config_data['pgAdmin4_login_credentials']
-                          ['test_new_password']),
+                          ['new_password']),
             new_password_confirm=(
                 config_data['pgAdmin4_login_credentials']
-                ['test_new_password']),
+                ['new_password']),
             respdata='Invalid password')),
 
-        # This testcase checks for valid password
+        # This test case checks for valid password
         ('TestCase for Changing Valid_Password', dict(
-            password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password']),
-            new_password=(config_data['pgAdmin4_login_credentials']
-                          ['test_new_password']),
-            new_password_confirm=(
-                config_data['pgAdmin4_login_credentials']
-                ['test_new_password']),
-            respdata='You successfully changed your password.')),
-        ('Reassigning_Password', dict(
-            test_case='reassigning_password',
-            password=(config_data['pgAdmin4_login_credentials']
-                      ['test_new_password']),
-            new_password=(config_data['pgAdmin4_login_credentials']
-                          ['test_login_password']),
+            valid_password='reassigning_password',
+            username=(config_data['pgAdmin4_test_user_credentials']
+                      ['login_username']),
+            password=(config_data['pgAdmin4_test_user_credentials']
+                      ['login_password']),
+            new_password=(config_data['pgAdmin4_test_user_credentials']
+                          ['new_password']),
             new_password_confirm=(
-                config_data['pgAdmin4_login_credentials']
-                ['test_login_password']),
+                config_data['pgAdmin4_test_user_credentials']
+                ['new_password']),
             respdata='You successfully changed your password.'))
-
     ]
 
+    @classmethod
+    def setUpClass(cls):
+        pass
+
     def runTest(self):
         """This function will check change password functionality."""
 
-        # Check for 'test_case' exists in self For reassigning the password.
-        # Password gets change in change password test case.
-        if 'test_case' in dir(self):
-            email = \
-                config_data['pgAdmin4_login_credentials'][
-                    'test_login_username']
-            password = \
-                config_data['pgAdmin4_login_credentials'][
-                    'test_new_password']
+        # Check for 'valid_password' exists in self to test 'valid password'
+        # test case
+        if 'valid_password' in dir(self):
+            response = self.tester.post('/user_management/user/', data=dict(
+                email=self.username, newPassword=self.password,
+                confirmPassword=self.password, active=1, role="2"),
+                                        follow_redirects=True)
+            user_id = json.loads(response.data.decode('utf-8'))['id']
+
+            # Logout the Administrator before login normal user
+            utils.logout_tester_account(self.tester)
+
             response = self.tester.post('/login', data=dict(
-                email=email, password=password), follow_redirects=True)
-
-        response = self.tester.get('/change', follow_redirects=True)
-        self.assertIn('pgAdmin 4 Password Change', response.data.decode(
-            'utf-8'))
-
-        response = self.tester.post('/change', data=dict(
-            password=self.password,
-            new_password=self.new_password,
-            new_password_confirm=self.new_password_confirm),
-                                    follow_redirects=True)
-        self.assertIn(self.respdata, response.data.decode('utf-8'))
+                email=self.username, password=self.password),
+                                        follow_redirects=True)
+            assert response.status_code == 200
+
+            # test the 'change password' test case
+            change_password(self)
+
+            # Delete the normal user after changing it's password
+            utils.logout_tester_account(self.tester)
+
+            # Login the Administrator before deleting normal user
+            utils.login_tester_account(self.tester)
+            response = self.tester.delete(
+                '/user_management/user/' + str(user_id),
+                follow_redirects=True)
+            assert response.status_code == 200
+        else:
+            change_password(self)
+
+    @classmethod
+    def tearDownClass(cls):
+        utils.login_tester_account(cls.tester)
diff --git a/web/pgadmin/browser/tests/test_login.py b/web/pgadmin/browser/tests/test_login.py
index b0ea361..f6bc6b5 100644
--- a/web/pgadmin/browser/tests/test_login.py
+++ b/web/pgadmin/browser/tests/test_login.py
@@ -24,20 +24,20 @@ class LoginTestCase(BaseTestGenerator):
         # This test case validates the invalid/incorrect password
         ('TestCase for Checking Invalid_Password', dict(
             email=(config_data['pgAdmin4_login_credentials']
-                   ['test_login_username']),
+                   ['login_username']),
             password=str(uuid.uuid4())[4:8],
             respdata='Invalid password')),
 
         # This test case validates the empty password field
         ('Empty_Password', dict(
             email=(config_data['pgAdmin4_login_credentials']
-                   ['test_login_username']), password='',
+                   ['login_username']), password='',
             respdata='Password not provided')),
 
         # This test case validates blank email field
         ('Empty_Email', dict(
             email='', password=(config_data['pgAdmin4_login_credentials']
-                                ['test_login_password']),
+                                ['login_password']),
             respdata='Email not provided')),
 
         # This test case validates empty email and password
@@ -49,7 +49,7 @@ class LoginTestCase(BaseTestGenerator):
         ('Invalid_Email', dict(
             email=str(uuid.uuid4())[1:6] + '@xyz.com',
             password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password']),
+                      ['login_password']),
             respdata='Specified user does not exist')),
 
         # This test case validates invalid email and password
@@ -62,21 +62,22 @@ class LoginTestCase(BaseTestGenerator):
         # to login pgAdmin 4
         ('Valid_Credentials', dict(
             email=(config_data['pgAdmin4_login_credentials']
-                   ['test_login_username']),
+                   ['login_username']),
             password=(config_data['pgAdmin4_login_credentials']
-                      ['test_login_password']),
+                      ['login_password']),
             respdata='Gravatar image for %s' %
                      config_data['pgAdmin4_login_credentials']
-                     ['test_login_username']))
+                     ['login_username']))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         """
         We need to logout the test client as we are testing scenarios of
         logging in the client like invalid password, invalid emails,
         empty credentials etc.
         """
-        utils.logout_tester_account(self.tester)
+        utils.logout_tester_account(cls.tester)
 
     def runTest(self):
         """This function checks login functionality."""
@@ -86,9 +87,10 @@ class LoginTestCase(BaseTestGenerator):
                                     follow_redirects=True)
         self.assertIn(self.respdata, response.data.decode('utf8'))
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         We need to again login the test client as soon as test scenarios
         finishes.
         """
-        utils.login_tester_account(self.tester)
+        utils.login_tester_account(cls.tester)
diff --git a/web/pgadmin/browser/tests/test_logout.py b/web/pgadmin/browser/tests/test_logout.py
index 729f7b1..5697de6 100644
--- a/web/pgadmin/browser/tests/test_logout.py
+++ b/web/pgadmin/browser/tests/test_logout.py
@@ -24,7 +24,8 @@ class LogoutTest(BaseTestGenerator):
         ('Logging Out', dict(respdata='Redirecting...'))
     ]
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(cls):
         pass
 
     def runTest(self):
@@ -33,9 +34,10 @@ class LogoutTest(BaseTestGenerator):
         response = self.tester.get('/logout')
         self.assertIn(self.respdata, response.data.decode('utf8'))
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(cls):
         """
         We need to again login the test client as soon as test scenarios
         finishes.
         """
-        utils.login_tester_account(self.tester)
+        utils.login_tester_account(cls.tester)
diff --git a/web/pgadmin/browser/tests/test_reset_password.py b/web/pgadmin/browser/tests/test_reset_password.py
index 9420c72..0dcf0bd 100644
--- a/web/pgadmin/browser/tests/test_reset_password.py
+++ b/web/pgadmin/browser/tests/test_reset_password.py
@@ -34,11 +34,12 @@ class ResetPasswordTestCase(BaseTestGenerator):
         # This test case validates the valid email id
         ('TestCase for Validating Valid_Email', dict(
             email=config_data['pgAdmin4_login_credentials']
-            ['test_login_username'], respdata='pgAdmin 4'))
+            ['login_username'], respdata='pgAdmin 4'))
     ]
 
-    def setUp(self):
-        logout_tester_account(self.tester)
+    @classmethod
+    def setUpClass(cls):
+        logout_tester_account(cls.tester)
 
     def runTest(self):
         """This function checks reset password functionality."""
@@ -51,5 +52,6 @@ class ResetPasswordTestCase(BaseTestGenerator):
             follow_redirects=True)
         self.assertIn(self.respdata, response.data.decode('utf-8'))
 
-    def tearDown(self):
-        login_tester_account(self.tester)
+    @classmethod
+    def tearDownClass(cls):
+        login_tester_account(cls.tester)
diff --git a/web/pgadmin/browser/tests/utils.py b/web/pgadmin/browser/tests/utils.py
new file mode 100644
index 0000000..18548ce
--- /dev/null
+++ b/web/pgadmin/browser/tests/utils.py
@@ -0,0 +1,21 @@
+# ##########################################################################
+#
+# #pgAdmin 4 - PostgreSQL Tools
+#
+# #Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# #This software is released under the PostgreSQL Licence
+#
+# ##########################################################################
+
+
+def change_password(self):
+    response = self.tester.get('/change', follow_redirects=True)
+    self.assertIn('pgAdmin 4 Password Change', response.data.decode(
+        'utf-8'))
+
+    response = self.tester.post('/change', data=dict(
+        password=self.password,
+        new_password=self.new_password,
+        new_password_confirm=self.new_password_confirm),
+                                follow_redirects=True)
+    self.assertIn(self.respdata, response.data.decode('utf-8'))
\ No newline at end of file
diff --git a/web/pgadmin/utils/route.py b/web/pgadmin/utils/route.py
index c7ef1f8..0226e8d 100644
--- a/web/pgadmin/utils/route.py
+++ b/web/pgadmin/utils/route.py
@@ -84,5 +84,6 @@ class BaseTestGenerator(unittest.TestCase):
         self.app = app
 
     # Initializing test_client.
-    def setTestClient(self, test_client):
-        self.tester = test_client
+    @classmethod
+    def setTestClient(cls, test_client):
+        cls.tester = test_client
diff --git a/web/regression/test_advanced_config.json.in b/web/regression/test_advanced_config.json.in
index c0d278b..fc8d98f 100644
--- a/web/regression/test_advanced_config.json.in
+++ b/web/regression/test_advanced_config.json.in
@@ -1,7 +1,7 @@
 {
-  "test_add_database_data": [
+  "add_database_data": [
    {
-    "test_privileges_acl": [
+    "privileges_acl": [
       {
         "grantee": "postgres",
         "grantor": "postgres",
@@ -19,9 +19,9 @@
         ]
       }
     ],
-    "test_conn_limit": -1,
-    "test_owner": "postgres",
-    "test_fun_acl": [
+    "conn_limit": -1,
+    "owner": "postgres",
+    "fun_acl": [
       {
         "grantee": "postgres",
         "grantor": "postgres",
@@ -34,7 +34,7 @@
         ]
       }
     ],
-    "test_seq_acl": [
+    "seq_acl": [
       {
         "grantee": "postgres",
         "grantor": "postgres",
@@ -57,7 +57,7 @@
         ]
       }
     ],
-    "test_tbl_acl": [
+    "tbl_acl": [
       {
         "grantee": "postgres",
         "grantor": "postgres",
@@ -75,7 +75,7 @@
         ]
       }
     ],
-    "test_type_acl": [
+    "type_acl": [
       {
         "grantee": "postgres",
         "grantor": "postgres",
@@ -88,112 +88,60 @@
         ]
       }
     ],
-    "test_encoding": "UTF8",
-    "test_name": "test_db_automation",
-    "test_privileges": [],
-    "test_securities": [],
-    "test_variables": []
-  },
-       {
-         "test_privileges_acl": [
-           {
-             "grantee": "enterprisedb",
-             "grantor": "enterprisedb",
-             "privileges": [
-               {
-                 "privilege_type": "C",
-                 "privilege": true,
-                 "with_grant": true
-               },
-               {
-                 "privilege_type": "T",
-                 "privilege": true,
-                 "with_grant": false
-               }
-             ]
-           }
-         ],
-         "test_conn_limit": -1,
-         "test_owner": "enterprisedb",
-         "test_fun_acl": [
-           {
-             "grantee": "enterprisedb",
-             "grantor": "enterprisedb",
-             "privileges": [
-               {
-                 "privilege_type": "X",
-                 "privilege": true,
-                 "with_grant": false
-               }
-             ]
-           }
-         ],
-         "test_seq_acl": [
-           {
-             "grantee": "enterprisedb",
-             "grantor": "enterprisedb",
-             "privileges": [
-               {
-                 "privilege_type": "r",
-                 "privilege": true,
-                 "with_grant": false
-               },
-               {
-                 "privilege_type": "w",
-                 "privilege": true,
-                 "with_grant": false
-               },
-               {
-                 "privilege_type": "U",
-                 "privilege": true,
-                 "with_grant": false
-               }
-             ]
-           }
-         ],
-         "test_tbl_acl": [
-           {
-             "grantee": "enterprisedb",
-             "grantor": "enterprisedb",
-             "privileges": [
-               {
-                 "privilege_type": "a",
-                 "privilege": true,
-                 "with_grant": true
-               },
-               {
-                 "privilege_type": "r",
-                 "privilege": true,
-                 "with_grant": false
-               }
-             ]
-           }
-         ],
-         "test_type_acl": [
-           {
-             "grantee": "enterprisedb",
-             "grantor": "enterprisedb",
-             "privileges": [
-               {
-                 "privilege_type": "U",
-                 "privilege": true,
-                 "with_grant": false
-               }
-             ]
-           }
-         ],
-         "test_encoding": "UTF8",
-         "test_name": "test_db_automation",
-         "test_privileges": [],
-         "test_securities": [],
-         "test_variables": []
-       }
+    "encoding": "UTF8",
+    "name": "test_db_automation",
+    "privileges": [],
+    "securities": [],
+    "variables": []
+  }
  ],
-
-  "test_db_update_data": [
+  "db_update_data": [
   {
-      "test_comment": "This is db update comment"
+      "comment": "This is db update comment"
   }
- ]
+ ],
+
+  "lr_credentials": {
+      "can_login": "true",
+      "conn_limit": -1,
+      "create_role": "true",
+      "role_inherit": "true",
+      "role_membership": [],
+      "lr_name":  "testlrg1",
+      "lr_password": "edb",
+      "lr_validity": "12/27/2016",
+      "sec_lable": [],
+      "variable":[
+                        {"name":"work_mem",
+                          "database":"postgres",
+                          "value":65
+                        }]
+    },
+  "lr_update_data": {
+      "comment": "This is db update comment"
+  },
+
+  "tablespc_credentials":[{
+    "tblspace_name": "test_tablespace",
+    "spc_seclable": [],
+    "spc_acl": [
+      {
+        "grantee":"postgres",
+        "grantor":"postgres",
+        "privileges":[
+          {
+            "privilege_type":"C",
+            "privilege":true,
+            "with_grant":false
+          }
+        ]
+      }
+    ],
+    "spc_opts": [],
+    "spc_user": "postgres"
+  }],
 
+    "tbspc_update_data": {
+    "comment": "This is tablespace update comment"
+  }
 }
\ No newline at end of file
diff --git a/web/regression/test_config.json.in b/web/regression/test_config.json.in
index 028d1e7..1328b6b 100644
--- a/web/regression/test_config.json.in
+++ b/web/regression/test_config.json.in
@@ -1,35 +1,31 @@
 {
   "pgAdmin4_login_credentials": {
-    "test_new_password": "NEWPASSWORD",
-    "test_login_password": "PASSWORD",
-    "test_login_username": "[email protected]"
+    "new_password": "NEWPASSWORD",
+    "login_password": "PASSWORD",
+    "login_username": "[email protected]"
   },
-  "test_server_group": 1,
-  "test_server_credentials": [
+  "pgAdmin4_test_user_credentials": {
+    "new_password": "NEWPASSWORD",
+    "login_password": "PASSWORD",
+    "login_username": "[email protected]"
+  },
+  "server_group": 1,
+  "server_credentials": [
     {
-      "test_name": "PostgreSQL 9.4",
-      "test_comment": "PostgreSQL 9.4 Server (EDB Installer)",
-      "test_db_username": "postgres",
-      "test_host": "localhost",
-      "test_db_password": "PASSWORD",
-      "test_db_port": 5432,
-      "test_maintenance_db": "postgres",
-      "test_sslmode": "prefer"
-    },
-     {
-       "test_name": "Postgres Plus Advanced Server 9.4",
-       "test_comment": "Postgres Plus Advanced 9.4 Server (EDB Installer)",
-       "test_db_username": "enterprisedb",
-       "test_host": "localhost",
-       "test_db_password": "edb",
-       "test_db_port": 5444,
-       "test_maintenance_db": "edb",
-       "test_sslmode": "prefer"
-     }
+      "name": "PostgreSQL 9.4",
+      "comment": "PostgreSQL 9.4 Server (EDB Installer)",
+      "db_username": "postgres",
+      "host": "localhost",
+      "db_password": "PASSWORD",
+      "db_port": 5432,
+      "maintenance_db": "postgres",
+      "sslmode": "prefer",
+      "tablespace_path": ""
+    }
   ],
-  "test_server_update_data": [
+  "server_update_data": [
     {
-      "test_comment": "This is test update comment"
+      "comment": "This is test update comment"
     }
   ]
 }
\ No newline at end of file
diff --git a/web/regression/test_setup.py b/web/regression/test_setup.py
index f7765bc..c805b1e 100644
--- a/web/regression/test_setup.py
+++ b/web/regression/test_setup.py
@@ -12,10 +12,24 @@ import os
 
 CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
 
-with open(CURRENT_PATH + '/test_config.json') as data_file:
-    config_data = json.load(data_file)
+# with open(CURRENT_PATH + '/test_config.json') as data_file:
+#     config_data = json.load(data_file)
+#
+# with open(CURRENT_PATH + '/test_advanced_config.json') as data_file:
+#     advanced_config_data = json.load(data_file)
+
+try:
+    with open(CURRENT_PATH + '/test_config.json') as data_file:
+        config_data = json.load(data_file)
+except:
+    with open(CURRENT_PATH + '/test_config.json.in') as data_file:
+        config_data = json.load(data_file)
 
-with open(CURRENT_PATH + '/test_advanced_config.json') as data_file:
-    advanced_config_data = json.load(data_file)
+try:
+    with open(CURRENT_PATH + '/test_advanced_config.json') as data_file:
+        advanced_config_data = json.load(data_file)
+except:
+    with open(CURRENT_PATH + '/test_advanced_config.json.in') as data_file:
+        advanced_config_data = json.load(data_file)
 
 pickle_path = os.path.join(CURRENT_PATH, 'parent_id.pkl')
diff --git a/web/regression/test_utils.py b/web/regression/test_utils.py
index 6be2bb2..16c2d46 100644
--- a/web/regression/test_utils.py
+++ b/web/regression/test_utils.py
@@ -9,16 +9,24 @@
 
 import os
 import pickle
-import json
-import uuid
 
-from test_setup import config_data, advanced_config_data, \
-    pickle_path
+from test_setup import config_data, pickle_path
 
-SERVER_URL = '/browser/server/obj/'
-SERVER_CONNECT_URL = 'browser/server/connect/'
-DATABASE_URL = '/browser/database/obj/'
-DATABASE_CONNECT_URL = 'browser/database/connect/'
+
+SERVER_GROUP = config_data['server_group']
+
+
+def get_pickle_id_dict():
+    """This function returns the empty dict of server config data"""
+
+    pickle_id_dict = {
+        "sid": [],  # server
+        "did": [],  # database
+        "lrid": [],  # role
+        "tsid": [],  # tablespace
+        "scid": []  # schema
+    }
+    return pickle_id_dict
 
 
 def get_ids(url=pickle_path):
@@ -34,43 +42,9 @@ def get_ids(url=pickle_path):
     output = open(url, 'rb')
     ids = pickle.load(output)
     output.close()
-
     return ids
 
 
-def verify_database(tester, server_group, server_id, db_id):
-    """
-    This function verifies that database is exists and whether it connect
-    successfully or not
-
-    :param tester: test client
-    :type tester: flask test client object
-    :param server_group: server group id
-    :type server_group: int
-    :param server_id: server id
-    :type server_id: str
-    :param db_id: database id
-    :type db_id: str
-    :return: temp_db_con
-    :rtype: list
-    """
-
-    # Connect to server
-    response = tester.post('{0}{1}/{2}'.format(
-        SERVER_CONNECT_URL, server_group, server_id), data=dict(
-        password=config_data['test_server_credentials'][0][
-            'test_db_password']),
-        follow_redirects=True)
-
-    # Connect to database
-    con_response = tester.post('{0}{1}/{2}/{3}'.format(
-        DATABASE_CONNECT_URL, server_group, server_id, db_id),
-        follow_redirects=True)
-    temp_db_con = json.loads(con_response.data.decode('utf-8'))
-
-    return temp_db_con
-
-
 def test_getnodes(tester=None):
     # Connect to server and database.
 
@@ -81,53 +55,14 @@ def test_getnodes(tester=None):
 
     server_ids = all_id["sid"]
     db_ids_dict = all_id["did"][0]
-    srv_grp = config_data['test_server_group']
 
     db_con = []
     for server_id in server_ids:
         db_id = db_ids_dict[int(server_id)]
-        db_con.append(verify_database(tester, srv_grp, server_id, db_id))
+        db_con.append(verify_database(tester, SERVER_GROUP, server_id, db_id))
     return db_con
 
 
-def get_db_data(server_connect_data):
-    """
-    This function is used to get advance config test data for appropriate
-    server
-
-    :param server_connect_data: list of server details
-    :return data: database details
-    :rtype: dict
-    """
-
-    adv_config_data = None
-    data = None
-    db_user = server_connect_data['data']['user']['name']
-
-    # Get the config data of appropriate db user
-    for config_test_data in advanced_config_data['test_add_database_data']:
-        if db_user == config_test_data['test_owner']:
-            adv_config_data = config_test_data
-
-    if adv_config_data is not None:
-        data = {
-            "datacl": adv_config_data['test_privileges_acl'],
-            "datconnlimit": adv_config_data['test_conn_limit'],
-            "datowner": adv_config_data['test_owner'],
-            "deffuncacl": adv_config_data['test_fun_acl'],
-            "defseqacl": adv_config_data['test_seq_acl'],
-            "deftblacl": adv_config_data['test_tbl_acl'],
-            "deftypeacl": adv_config_data['test_type_acl'],
-            "encoding": adv_config_data['test_encoding'],
-            "name": str(uuid.uuid4())[1:8],
-            "privileges": adv_config_data['test_privileges'],
-            "securities": adv_config_data['test_securities'],
-            "variables": adv_config_data['test_variables']
-        }
-
-    return data
-
-
 def login_tester_account(tester):
     """
     This function login the test account using credentials mentioned in
@@ -139,9 +74,9 @@ def login_tester_account(tester):
     """
 
     email = \
-        config_data['pgAdmin4_login_credentials']['test_login_username']
+        config_data['pgAdmin4_login_credentials']['login_username']
     password = \
-        config_data['pgAdmin4_login_credentials']['test_login_password']
+        config_data['pgAdmin4_login_credentials']['login_password']
     response = tester.post('/login', data=dict(
         email=email, password=password), follow_redirects=True)
 
@@ -158,6 +93,7 @@ def logout_tester_account(tester):
     response = tester.get('/logout')
 
 
+# Config data for parent_id.pkl
 def get_config_data():
     """
     This function get the data related to server group and database
@@ -168,23 +104,18 @@ def get_config_data():
     """
 
     db_data = []
+    pickle_id_dict = get_pickle_id_dict()
+    server_group = config_data['server_group']
 
-    pickle_id_dict = {
-        "sid": [],  # server
-        "did": []  # database
-    }
-
-    server_group = config_data['test_server_group']
-
-    for srv in config_data['test_server_credentials']:
-        data = {"name": srv['test_name'],
+    for srv in config_data['server_credentials']:
+        data = {"name": srv['name'],
                 "comment": "",
-                "host": srv['test_host'],
-                "port": srv['test_db_port'],
-                "db": srv['test_maintenance_db'],
-                "username": srv['test_db_username'],
+                "host": srv['host'],
+                "port": srv['db_port'],
+                "db": srv['maintenance_db'],
+                "username": srv['db_username'],
                 "role": "",
-                "sslmode": srv['test_sslmode']}
+                "sslmode": srv['sslmode']}
         db_data.append(data)
     return server_group, db_data, pickle_id_dict
 
@@ -205,40 +136,12 @@ def write_parent_id(response_data, pickle_id_dict):
         existed_server_id = open(pickle_path, 'rb')
         pickle_id_dict = pickle.load(existed_server_id)
 
-    pickle_id_dict["sid"].append(server_id)
+    pickle_id_dict["sid"].append(str(server_id))
     output = open(pickle_path, 'wb')
     pickle.dump(pickle_id_dict, output)
     output.close()
 
 
-def write_db_parent_id(response_data):
-    """
-    This function writes the server and database related data like server
-    name, server id , database name, database id etc.
-
-    :param response_data: server and databases details
-    :type response_data: dict
-    :return: None
-    """
-
-    db_id = response_data['node']['_id']
-    server_id = response_data['node']['_pid']
-    if os.path.isfile(pickle_path):
-        existing_server_id = open(pickle_path, 'rb')
-        tol_server_id = pickle.load(existing_server_id)
-        pickle_id_dict = tol_server_id
-        if 'did' in pickle_id_dict:
-            if pickle_id_dict['did']:
-                # Add the db_id as value in dict
-                pickle_id_dict["did"][0].update({server_id: db_id})
-            else:
-                # Create new dict with server_id and db_id
-                pickle_id_dict["did"].append({server_id: db_id})
-        db_output = open(pickle_path, 'wb')
-        pickle.dump(pickle_id_dict, db_output)
-        db_output.close()
-
-
 def delete_parent_id_file():
     """
     This function deletes the file parent_id.pkl which contains server and
@@ -250,148 +153,3 @@ def delete_parent_id_file():
     if os.path.isfile(pickle_path):
         os.remove(pickle_path)
 
-
-def add_server(tester):
-    """
-    This function add the server in the existing server group
-
-    :param tester: test object
-    :type tester: flask test object
-    :return:None
-    """
-
-    server_group, db_data, pickle_id_dict = get_config_data()
-    url = "{0}{1}/".format(SERVER_URL, server_group)
-    for db_detail in db_data:
-        response = tester.post(url, data=json.dumps(db_detail),
-                               content_type='html/json')
-        response_data = json.loads(response.data.decode())
-        write_parent_id(response_data, pickle_id_dict)
-
-
-def get_server(tester):
-    """
-    This function gets the added serer details
-
-    :param tester: test client object
-    :type tester: flask test object
-    :return: response_data
-    :rtype: list
-    """
-
-    all_id = get_ids()
-    server_ids = all_id["sid"]
-    server_group = config_data['test_server_group']
-    for server_id in server_ids:
-        response = tester.get(SERVER_URL + str(server_group) + '/' +
-                              str(server_id),
-                              follow_redirects=True)
-        response_data = json.loads(response.data.decode())
-
-
-def connect_server(tester):
-    """
-    This function used to connect added server
-
-    :param tester:test client object
-    :type tester: flask test object
-    :return: server_connect, server_group, server_id
-    :rtype: server_connect:dict, server_group:dict, server_id:str
-    """
-
-    server_connect = []
-    servers = []
-
-    srv_id = get_ids()
-    server_ids = srv_id["sid"]
-    server_group = config_data['test_server_group']
-
-    # Connect to all servers
-    for server_id in server_ids:
-        response = tester.post(SERVER_CONNECT_URL + str(server_group) +
-                               '/' + server_id,
-                               data=dict(
-                                   password=config_data
-                                   ['test_server_credentials'][0]
-                                   ['test_db_password']),
-                               follow_redirects=True)
-        server_connect_detail = json.loads(response.data.decode())
-        connect_database(tester, server_connect_detail, server_id,
-                         server_group)
-        server_connect.append(server_connect_detail)
-        servers.append(server_id)
-    return server_connect, server_group, servers
-
-
-def connect_database(tester, server_connect, server_id, server_group):
-    """
-    This function is used to connect database and writes it's details to
-    file 'parent_id.pkl'
-
-    :param tester: test client object
-    :type tester: flask test client object
-    :param server_connect: server's data
-    :type server_connect: dict
-    :param server_id: server id
-    :type server_id: str
-    :param server_group: server group name
-    :type server_group: str
-    :return: None
-    """
-
-    if server_connect['data']['connected']:
-        db_data = get_db_data(server_connect)
-        db_response = tester.post(
-            DATABASE_URL + str(server_group) + "/" + server_id + "/",
-            data=json.dumps(db_data),
-            content_type='html/json')
-        response_data = json.loads(db_response.data.decode())
-        write_db_parent_id(response_data)
-
-
-def delete_server(tester):
-    """
-    This function used to delete the added servers
-
-    :param tester: test client object
-    :return: None
-    """
-
-    srv_grp = config_data['test_server_group']
-    all_id = get_ids()
-    server_ids = all_id["sid"]
-    url = SERVER_URL + str(srv_grp) + "/"
-
-    # Call api to delete the servers
-    for server_id in server_ids:
-        response = tester.delete(url + str(server_id))
-        assert response.status_code == 200
-        response_data = json.loads(response.data.decode())
-        assert response_data['success'] == 1
-
-
-def delete_database(tester):
-    """
-    This function used to delete the added databases
-
-    :param tester: test client object
-    :return: None
-    """
-
-    srv_grp = config_data['test_server_group']
-    all_id = get_ids()
-    server_ids = all_id["sid"]
-    db_ids_dict = all_id['did'][0]
-
-    db_con = test_getnodes(tester)
-    if len(db_con) == 0:
-        raise Exception("No database(s) to delete.")
-
-    for server_id in server_ids:
-        db_id = db_ids_dict[int(server_id)]
-        response = tester.delete(DATABASE_URL + str(srv_grp) + '/' +
-                                 str(server_id) + '/' + str(db_id),
-                                 follow_redirects=True)
-        assert response.status_code == 200
-        response_data = json.loads(response.data.decode('utf-8'))
-        assert response_data['success'] == 1


^ permalink  raw  reply  [nested|flat] 29+ messages in thread

* Re: pgAdmin IV : Unittest modular patch
@ 2016-08-09 15:06  Dave Page <[email protected]>
  parent: Navnath Gadakh <[email protected]>
  0 siblings, 0 replies; 29+ messages in thread

From: Dave Page @ 2016-08-09 15:06 UTC (permalink / raw)
  To: Navnath Gadakh <[email protected]>; +Cc: pgadmin-hackers; Kanchan Mohitey <[email protected]>

Thanks - applied with some minor wording and README tweaks.

On Tue, Aug 9, 2016 at 10:19 AM, Navnath Gadakh
<[email protected]> wrote:
> Hi Dave,
>
> On Mon, Aug 8, 2016 at 9:15 PM, Dave Page <[email protected]>
> wrote:
>>
>> Hi
>>
>> I guess you need to test if tablespace_path is omitted, not just empty?
>
>     Yes, thats right.. Please find the updated patch.
>>
>>
>> This function test the add tablespace scenario (Check Tablespace Node) ...
>> ERROR
>>
>> ======================================================================
>> ERROR: setUpClass
>>
>> (pgadmin.browser.server_groups.servers.tablespaces.tests.test_tbspc_put.TableSpaceUpdateTestCase)
>> ----------------------------------------------------------------------
>> Traceback (most recent call last):
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_put.py",
>> line 48, in setUpClass
>>     cls.server_group, cls.server_ids)
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
>> line 122, in add_table_space
>>     data = get_tablespace_data(server_connect)
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
>> line 41, in get_tablespace_data
>>     config_test_data['spc_location'] = server_config['tablespace_path']
>> KeyError: 'tablespace_path'
>>
>> ======================================================================
>> ERROR: setUpClass
>>
>> (pgadmin.browser.server_groups.servers.tablespaces.tests.test_tbspc_delete.TableSpaceDeleteTestCase)
>> ----------------------------------------------------------------------
>> Traceback (most recent call last):
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_delete.py",
>> line 46, in setUpClass
>>     cls.server_group, cls.server_ids)
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
>> line 122, in add_table_space
>>     data = get_tablespace_data(server_connect)
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
>> line 41, in get_tablespace_data
>>     config_test_data['spc_location'] = server_config['tablespace_path']
>> KeyError: 'tablespace_path'
>>
>> ======================================================================
>> ERROR: setUpClass
>>
>> (pgadmin.browser.server_groups.servers.tablespaces.tests.test_tbspc_get.TablespaceGetTestCase)
>> ----------------------------------------------------------------------
>> Traceback (most recent call last):
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_get.py",
>> line 45, in setUpClass
>>     cls.server_group, cls.server_ids)
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
>> line 122, in add_table_space
>>     data = get_tablespace_data(server_connect)
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
>> line 41, in get_tablespace_data
>>     config_test_data['spc_location'] = server_config['tablespace_path']
>> KeyError: 'tablespace_path'
>>
>> ======================================================================
>> ERROR: runTest
>> (pgadmin.browser.server_groups.servers.tablespaces.tests.test_tbspc_add.TableSpaceAddTestCase)
>> This function test the add tablespace scenario (Check Tablespace Node)
>> ----------------------------------------------------------------------
>> Traceback (most recent call last):
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/test_tbspc_add.py",
>> line 47, in runTest
>>     self.server_ids)
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
>> line 122, in add_table_space
>>     data = get_tablespace_data(server_connect)
>>   File
>> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/tablespaces/tests/utils.py",
>> line 41, in get_tablespace_data
>>     config_test_data['spc_location'] = server_config['tablespace_path']
>> KeyError: 'tablespace_path'
>>
>> ----------------------------------------------------------------------
>> Ran 14 tests in 9.326s
>>
>> FAILED (errors=4)
>>
>> On Mon, Aug 8, 2016 at 3:07 PM, Navnath Gadakh
>> <[email protected]> wrote:
>> > Hi Dave,
>> >     Please find the updated patch for API unit test cases for Roles and
>> > Tablespaces nodes
>> > As we finalized
>> > Now,
>> >    1. The user will specify the tablespace path in test_config.json.in
>> >    2.  If tablespace path not found, skip the test cases for that
>> > server(Only tablespace test cases)
>> >    3.  Add the skipped test summary in the test result. (Now it's
>> > showing on
>> > console + in log file, but need to update in a final enhanced test
>> > summary
>> > report. Which is research point we will work on that after finishing all
>> > nodes API test cases)
>> >    4.  Removed the test_ prefix from the values in the config files.
>> >
>> > Thanks!
>> >
>> >
>> > On Thu, Aug 4, 2016 at 5:55 PM, Dave Page <[email protected]>
>> > wrote:
>> >>
>> >> On Thu, Aug 4, 2016 at 1:02 PM, Navnath Gadakh
>> >> <[email protected]> wrote:
>> >> > Hi Dave,
>> >> >
>> >> > On Thu, Aug 4, 2016 at 4:04 PM, Dave Page
>> >> > <[email protected]>
>> >> > wrote:
>> >> >>
>> >> >> Hi
>> >> >>
>> >> >> On Thu, Aug 4, 2016 at 10:27 AM, Navnath Gadakh
>> >> >> <[email protected]> wrote:
>> >> >>
>> >> >> >> Oh - does the per-server config override the main config? That's
>> >> >> >> useful. So anything that's in test_advanced_config.py can be
>> >> >> >> overridden on a per-server basis in test_config.py?
>> >> >> >
>> >> >> >     No.
>> >> >> >     per-server i.e advance config(test_advanced_config.json.in)
>> >> >> > and
>> >> >> > main
>> >> >> > config(test_config.json) both are different files. In main config
>> >> >> > we
>> >> >> > just
>> >> >> > mention the server’s credentials.(We can also mention per server
>> >> >> > credentails) and in test_advanced_config.json.in(here we say
>> >> >> > per-server
>> >> >> > config)
>> >> >> > we mention the advanced configurations i.e. test data for each
>> >> >> > node.
>> >> >>
>> >> >> OK.
>> >> >>
>> >> >> >     So, let's summarize the discussion:
>> >> >> >     - Let user specify the tablespace path in
>> >> >> > test_advanced_config.json.in
>> >> >>
>> >> >> No - test_config.py. It should be per-server.
>> >> >
>> >> >      We don't have a file named 'test_config.py' but we have a
>> >> > server's
>> >> > credential file named 'test_config.json'.
>> >> >      So, you are saying the tablespace path to be added in
>> >> > 'test_config.json'.
>> >> >      Am I correct?
>> >>
>> >> Yeah, sorry. It should be a property of the server configuration.
>> >>
>> >>
>> >> --
>> >> Dave Page
>> >> VP, Chief Architect, Tools & Installers
>> >> EnterpriseDB: http://www.enterprisedb.com
>> >> The Enterprise PostgreSQL Company
>> >>
>> >> Blog: http://pgsnake.blogspot.com
>> >> Twitter: @pgsnake
>> >
>> >
>> >
>> >
>> > --
>> > Thanks,
>> > Navnath Gadakh
>> > Software Engineer
>> > EnterpriseDB Corporation
>> > Mobile: +91 9975389878
>> >
>> >
>>
>>
>>
>> --
>> Dave Page
>> VP, Chief Architect, Tools & Installers
>> EnterpriseDB: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>
>
>
>
> --
> Thanks,
> Navnath Gadakh
> Software Engineer
> EnterpriseDB Corporation
> Mobile: +91 9975389878
>
>



-- 
Dave Page
VP, Chief Architect, Tools & Installers
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers




^ permalink  raw  reply  [nested|flat] 29+ messages in thread


end of thread, other threads:[~2016-08-09 15:06 UTC | newest]

Thread overview: 29+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2016-07-08 13:30 Fwd: pgAdmin IV : Unittest modular patch Navnath Gadakh <[email protected]>
2016-07-11 11:41 ` Dave Page <[email protected]>
2016-07-11 13:16   ` Navnath Gadakh <[email protected]>
2016-07-15 12:53     ` Dave Page <[email protected]>
2016-07-18 12:45       ` Navnath Gadakh <[email protected]>
2016-07-18 13:55         ` Dave Page <[email protected]>
2016-07-19 04:19           ` Khushboo Vashi <[email protected]>
2016-07-22 13:22             ` Navnath Gadakh <[email protected]>
2016-07-22 16:18               ` Dave Page <[email protected]>
2016-07-25 16:57                 ` Navnath Gadakh <[email protected]>
2016-07-27 12:19                 ` Navnath Gadakh <[email protected]>
2016-07-27 14:42                   ` Dave Page <[email protected]>
2016-07-27 15:27                     ` Priyanka Shendge <[email protected]>
2016-07-28 07:12                     ` Navnath Gadakh <[email protected]>
2016-08-01 09:47                       ` Dave Page <[email protected]>
2016-08-01 09:54                         ` Navnath Gadakh <[email protected]>
2016-08-01 10:26                           ` Dave Page <[email protected]>
2016-08-02 14:58                             ` Navnath Gadakh <[email protected]>
2016-08-03 09:15                               ` Dave Page <[email protected]>
2016-08-03 13:01                                 ` Navnath Gadakh <[email protected]>
2016-08-03 15:02                                   ` Dave Page <[email protected]>
2016-08-04 09:27                                     ` Navnath Gadakh <[email protected]>
2016-08-04 10:34                                       ` Dave Page <[email protected]>
2016-08-04 12:02                                         ` Navnath Gadakh <[email protected]>
2016-08-04 12:25                                           ` Dave Page <[email protected]>
2016-08-08 14:07                                             ` Navnath Gadakh <[email protected]>
2016-08-08 15:45                                               ` Dave Page <[email protected]>
2016-08-09 09:19                                                 ` Navnath Gadakh <[email protected]>
2016-08-09 15:06                                                   ` Dave Page <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox