Here's an updated patch which polls to wait for the app to start instead of sleeping for 10 seconds.
On Thu, Jan 19, 2017 at 5:07 PM, George Gelashvili <ggelashv...@pivotal.io> wrote: > > Here is an updated patch which starts the server up when the test starts > and uses the values from config.py for server name etc. It still requires > installing chromedriver before running. Should we add something to the > readme about that? > > On Tue, Jan 17, 2017 at 11:09 AM, Atira Odhner <aodh...@pivotal.io> wrote: > >> Thanks for your feedback, Dave! >> >> We can put the tests under the regression directory. I think that makes >> sense. >> I'm not picturing these tests being module specific, but we may want to >> enable running it as a separate suite of tests. >> >> Thanks for the callout about the port and title. We'll make sure those >> are pulled from config or that the pgAdmin server is spun up by the test >> with specific values. >> >> I have a couple ideas about why the test might not have been running for >> you. I think the patch we attached didn't spin up its own pgAdmin yet and >> it definitely doesn't fill in username/password if your app is running that >> way. That's part of the WIP-ness :-P >> >> -Tira >> >> Hi >> >> On Thu, Jan 12, 2017 at 10:41 PM, George Gelashvili >> <ggelashvili(at)pivotal(dot)io> wrote: >> > here's the patch we forgot to attach. Also, you can see work on our branch >> > at: >> > https://github.com/pivotalsoftware/pgadmin4/tree/pivotal/acceptance-tests >> > >> > On Thu, Jan 12, 2017 at 5:26 PM, George Gelashvili >> > <ggelashvili(at)pivotal(dot)io> >> > wrote: >> >> >> >> Hi there, >> >> >> >> We are working on browser-automation-based acceptance tests that exercise >> >> pgAdmin4 the way a user might. >> >> Nice! >> >> >> The first "connect to database" test works, but at the moment depends on >> >> Chrome and chromedriver. We would appreciate feedback on any possible >> >> license or code style issues at this point, as well as any thoughts on >> >> adding this sort of test to the codebase. >> >> A few thoughts: >> >> - If these tests are to run as part of the regression suite, the >> framework for them should live under that directory. >> >> - Are any of the tests likely to be module-specific? If so, they >> should really be part of the relevant module as the regression tests >> are. If they're more general/less tightly coupled, then I don't see a >> problem with them residing where they are. >> >> - Please take care not to include changes to .gitgnore files that >> aren't relevant to the rest of us. >> >> - The port number is hard-coded in the test. >> >> - You've hard-coded the string "pgAdmin 4". We've tried to keep that >> title as a config option in config.py, so you should pull the string >> from there rather than hard-coding it. >> >> - The connect test fails for me (Mac, Python 2.7). I have a suspicion >> that this may be because when the test starts chromedriver, OS X >> prompts the user about whether a listening port should be opened, but >> the tests don't wait (though, I tested with 3 servers configured and >> it failed with the same error on the second and third as well, long >> after I clicked OK on the prompt): >> >> Traceback (most recent call last): >> File >> "/Users/dpage/git/pgadmin4/web/acceptance/test_connects_to_database.py", >> line 32, in runTest >> self.assertEqual("pgAdmin 4", self.driver.title) >> AssertionError: 'pgAdmin 4' != u'localhost' >> >> - Please keep tests in the pgadmin. namespace (pgadmin.acceptance.??). >> >> - It looks like running a single test won't work yet (because of >> TestsGeneratorRegistry.load_generators('pgadmin.%s.tests' % >> arguments['pkg'])) >> >> Thanks! >> >> -- >> Dave Page >> Blog: http://pgsnake.blogspot.com >> >> Twitter: @pgsnake >> >> EnterpriseDB UK: http://www.enterprisedb.com >> The Enterprise PostgreSQL Company >> >> >> >
diff --git a/requirements_py2.txt b/requirements_py2.txt index 51170a45..de167121 100644 --- a/requirements_py2.txt +++ b/requirements_py2.txt @@ -36,6 +36,7 @@ testscenarios==0.5.0 testtools==2.0.0 traceback2==1.4.0 unittest2==1.1.0 +selenium==3.0.2 Werkzeug==0.9.6 WTForms==2.0.2 sqlparse==0.1.19 diff --git a/requirements_py3.txt b/requirements_py3.txt index f68db7a8..9565a6e4 100644 --- a/requirements_py3.txt +++ b/requirements_py3.txt @@ -35,6 +35,7 @@ testscenarios==0.5.0 testtools==2.0.0 traceback2==1.4.0 unittest2==1.1.0 +selenium==3.0.2 Werkzeug==0.9.6 WTForms==2.0.2 sqlparse==0.1.19 diff --git a/web/pgadmin/acceptance/__init__.py b/web/pgadmin/acceptance/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/web/pgadmin/acceptance/tests/__init__.py b/web/pgadmin/acceptance/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/web/pgadmin/acceptance/tests/test_connects_to_database.py b/web/pgadmin/acceptance/tests/test_connects_to_database.py new file mode 100644 index 00000000..2c4f85c4 --- /dev/null +++ b/web/pgadmin/acceptance/tests/test_connects_to_database.py @@ -0,0 +1,123 @@ +############################################################# +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2017, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +############################################################## + +import time + +from selenium import webdriver +from selenium.common.exceptions import NoSuchElementException +from selenium.webdriver import ActionChains + +from pgadmin.utils.route import BaseTestGenerator + +import subprocess +import os +import signal +import config + + +class ConnectsToDatabase(BaseTestGenerator): + """ + Tests that a database connection can be created from the UI + """ + + def setUp(self): + if (config.SERVER_MODE): + self.skipTest("Currently, config is set to start pgadmin in server mode. " + "This test doesn't know username and password so doesn't work in server mode") + + self.pgadmin_process = subprocess.Popen(["python", "pgAdmin4.py"], shell=False, preexec_fn=os.setsid, stderr=open(os.devnull, 'w')) + + self.driver = webdriver.Chrome() + self.server_config = self.server + + print("opening browser") + self.driver.get("http://" + config.DEFAULT_SERVER + ":" + str(config.DEFAULT_SERVER_PORT)) + self._wait_for_app() + + def runTest(self): + self.assertEqual(config.APP_NAME, self.driver.title) + self._wait_for_spinner_to_disappear() + + self._find_by_xpath("//*[@class='aciTreeText' and .='Servers']").click() + self.driver.find_element_by_link_text("Object").click() + ActionChains(self.driver) \ + .move_to_element(self.driver.find_element_by_link_text("Create")) \ + .perform() + self._find_by_partial_link_text("Server...").click() + + self._fill_input_by_xpath("name", self.server_config['name']) + self._find_by_partial_link_text("Connection").click() + self._fill_input_by_xpath("host", self.server_config['host']) + self._fill_input_by_xpath("port", self.server_config['port']) + self._fill_input_by_xpath("username", self.server_config['username']) + self._fill_input_by_xpath("password", self.server_config['db_password']) + self._find_by_xpath("//button[contains(.,'Save')]").click() + + self._find_by_xpath("//*[@id='tree']//*[.='" + self.server_config['name'] + "']") + + def tearDown(self): + self.driver.close() + os.killpg(os.getpgid(self.pgadmin_process.pid), signal.SIGTERM) + + def failureException(self, *args, **kwargs): + self.driver.save_screenshot('/tmp/pgadmin_test_screenshot.png') + return AssertionError(*args, **kwargs) + + def _find_by_xpath(self, xpath): + return self._wait_for_element(lambda: self.driver.find_element_by_xpath(xpath)) + + def _find_by_partial_link_text(self, link_text): + return self._wait_for_element(lambda: self.driver.find_element_by_partial_link_text(link_text)) + + def _fill_input_by_xpath(self, field_name, field_content): + self._find_by_xpath("//input[@name='" + field_name + "']").clear() + self._find_by_xpath("//input[@name='" + field_name + "']").send_keys( + field_content) + + def _wait_for_element(self, find_method_with_args): + def element_if_it_exists(): + try: + element = find_method_with_args() + if element.is_displayed() & element.is_enabled(): + return element + except NoSuchElementException: + return False + + return self.__wait_for("element to exist", element_if_it_exists) + + def _wait_for_spinner_to_disappear(self): + def spinner_has_disappeared(): + try: + self.driver.find_element_by_id("pg-spinner") + return False + except NoSuchElementException: + return True + + self.__wait_for("spinner to disappear", spinner_has_disappeared) + + def _wait_for_app(self): + def page_shows_app(): + self.driver.refresh() + return self.driver.title == config.APP_NAME + + self.__wait_for("app to start", page_shows_app) + + def __wait_for(self, waiting_for_message, condition_met_function): + timeout = 5 + time_waited = 0 + sleep_time = 0.01 + + while time_waited < timeout: + result = condition_met_function() + if(result): + return result + time_waited += sleep_time + time.sleep(sleep_time) + + self.fail("Timed out waiting for " + waiting_for_message) diff --git a/web/pgadmin/utils/route.py b/web/pgadmin/utils/route.py index f18d2c18..fed26a0f 100644 --- a/web/pgadmin/utils/route.py +++ b/web/pgadmin/utils/route.py @@ -54,20 +54,25 @@ class TestsGeneratorRegistry(ABCMeta): ABCMeta.__init__(cls, name, bases, d) @classmethod - def load_generators(cls, pkg): + def load_generators(cls, *pkgs): cls.registry = dict() + all_modules = [] + + for pkg in pkgs: + all_modules += find_modules(pkg, False, True) + + # Check for SERVER mode - if config.SERVER_MODE: - for module_name in find_modules(pkg, False, True): + for module_name in all_modules: + if config.SERVER_MODE: try: if "tests." in str(module_name): import_module(module_name) except ImportError: traceback.print_exc(file=sys.stderr) - else: - for module_name in find_modules(pkg, False, True): + else: try: # Exclude the test cases in browser node if SERVER_MODE # is False diff --git a/web/regression/.gitignore b/web/regression/.gitignore index 0581810b..723fce7e 100644 --- a/web/regression/.gitignore +++ b/web/regression/.gitignore @@ -1,4 +1,5 @@ parent_id.pkl regression.log +test_greenplum_config.json test_advanced_config.json test_config.json
-- Sent via pgadmin-hackers mailing list (pgadmin-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgadmin-hackers