OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Performance tests for Chrome Endure (long-running perf tests on Chrome). | 6 """Performance tests for Chrome Endure (long-running perf tests on Chrome). |
7 | 7 |
8 This module accepts the following environment variable inputs: | 8 This module accepts the following environment variable inputs: |
9 TEST_LENGTH: The number of seconds in which to run each test. | 9 TEST_LENGTH: The number of seconds in which to run each test. |
10 PERF_STATS_INTERVAL: The number of seconds to wait in-between each sampling | 10 PERF_STATS_INTERVAL: The number of seconds to wait in-between each sampling |
(...skipping 15 matching lines...) Expand all Loading... | |
26 import time | 26 import time |
27 | 27 |
28 import perf | 28 import perf |
29 import pyauto_functional # Must be imported before pyauto. | 29 import pyauto_functional # Must be imported before pyauto. |
30 import pyauto | 30 import pyauto |
31 import pyauto_errors | 31 import pyauto_errors |
32 import pyauto_utils | 32 import pyauto_utils |
33 import remote_inspector_client | 33 import remote_inspector_client |
34 import selenium.common.exceptions | 34 import selenium.common.exceptions |
35 from selenium.webdriver.support.ui import WebDriverWait | 35 from selenium.webdriver.support.ui import WebDriverWait |
36 import webpagereplay | |
36 | 37 |
37 | 38 |
38 class NotSupportedEnvironmentError(RuntimeError): | 39 class NotSupportedEnvironmentError(RuntimeError): |
39 """Represent an error raised since the environment (OS) is not supported.""" | 40 """Represent an error raised since the environment (OS) is not supported.""" |
40 pass | 41 pass |
41 | 42 |
43 | |
42 class ChromeEndureBaseTest(perf.BasePerfTest): | 44 class ChromeEndureBaseTest(perf.BasePerfTest): |
43 """Implements common functionality for all Chrome Endure tests. | 45 """Implements common functionality for all Chrome Endure tests. |
44 | 46 |
45 All Chrome Endure test classes should inherit from this class. | 47 All Chrome Endure test classes should inherit from this class. |
46 """ | 48 """ |
47 | 49 |
48 _DEFAULT_TEST_LENGTH_SEC = 60 * 60 * 6 # Tests run for 6 hours. | 50 _DEFAULT_TEST_LENGTH_SEC = 60 * 60 * 6 # Tests run for 6 hours. |
49 _GET_PERF_STATS_INTERVAL = 60 * 5 # Measure perf stats every 5 minutes. | 51 _GET_PERF_STATS_INTERVAL = 60 * 5 # Measure perf stats every 5 minutes. |
50 # TODO(dennisjeffrey): Do we still need to tolerate errors? | 52 # TODO(dennisjeffrey): Do we still need to tolerate errors? |
51 _ERROR_COUNT_THRESHOLD = 50 # Number of ChromeDriver errors to tolerate. | 53 _ERROR_COUNT_THRESHOLD = 50 # Number of ChromeDriver errors to tolerate. |
52 _DEEP_MEMORY_PROFILE = False | 54 _DEEP_MEMORY_PROFILE = False |
53 _DEEP_MEMORY_PROFILE_INTERVAL = _GET_PERF_STATS_INTERVAL | 55 _DEEP_MEMORY_PROFILE_INTERVAL = _GET_PERF_STATS_INTERVAL |
54 _DEEP_MEMORY_PROFILE_SAVE = False | 56 _DEEP_MEMORY_PROFILE_SAVE = False |
55 | 57 |
56 _DMPROF_DIR_PATH = os.path.join( | 58 _DMPROF_DIR_PATH = os.path.join( |
57 os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, | 59 os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, |
58 'tools', 'deep_memory_profiler') | 60 'tools', 'deep_memory_profiler') |
59 | 61 |
60 _DMPROF_SCRIPT_PATH = os.path.join(_DMPROF_DIR_PATH, 'dmprof') | 62 _DMPROF_SCRIPT_PATH = os.path.join(_DMPROF_DIR_PATH, 'dmprof') |
61 | 63 |
62 _CHROME_BIN_PATH = os.path.join(perf.BasePerfTest.BrowserPath(), 'chrome') | 64 _CHROME_BIN_PATH = os.path.join(perf.BasePerfTest.BrowserPath(), 'chrome') |
63 | 65 |
64 def setUp(self): | 66 def setUp(self): |
67 # The environment variable for the usage of Web Page Replay. | |
68 # It must be parsed before perf.BasePerfTest.setUp() | |
69 self._use_wpr = 'ENDURE_NO_WPR' not in os.environ | |
70 | |
65 # The environment variables for the Deep Memory Profiler must be set | 71 # The environment variables for the Deep Memory Profiler must be set |
66 # before perf.BasePerfTest.setUp() to inherit them to Chrome. | 72 # before perf.BasePerfTest.setUp() to inherit them to Chrome. |
67 self._deep_memory_profile = self._GetDeepMemoryProfileEnv( | 73 self._deep_memory_profile = self._GetDeepMemoryProfileEnv( |
68 'DEEP_MEMORY_PROFILE', bool, self._DEEP_MEMORY_PROFILE) | 74 'DEEP_MEMORY_PROFILE', bool, self._DEEP_MEMORY_PROFILE) |
69 | 75 |
70 self._deep_memory_profile_interval = self._GetDeepMemoryProfileEnv( | 76 self._deep_memory_profile_interval = self._GetDeepMemoryProfileEnv( |
71 'DEEP_MEMORY_PROFILE_INTERVAL', int, self._DEEP_MEMORY_PROFILE_INTERVAL) | 77 'DEEP_MEMORY_PROFILE_INTERVAL', int, self._DEEP_MEMORY_PROFILE_INTERVAL) |
72 | 78 |
73 if self._deep_memory_profile: | 79 if self._deep_memory_profile: |
74 if not self.IsLinux(): | 80 if not self.IsLinux(): |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
173 # The same with setUp, but need to fetch the environment variable since | 179 # The same with setUp, but need to fetch the environment variable since |
174 # ExtraChromeFlags is called before setUp. | 180 # ExtraChromeFlags is called before setUp. |
175 deep_memory_profile = self._GetDeepMemoryProfileEnv( | 181 deep_memory_profile = self._GetDeepMemoryProfileEnv( |
176 'DEEP_MEMORY_PROFILE', bool, self._DEEP_MEMORY_PROFILE) | 182 'DEEP_MEMORY_PROFILE', bool, self._DEEP_MEMORY_PROFILE) |
177 | 183 |
178 # Ensure Chrome enables remote debugging on port 9222. This is required to | 184 # Ensure Chrome enables remote debugging on port 9222. This is required to |
179 # interact with Chrome's remote inspector. | 185 # interact with Chrome's remote inspector. |
180 extra_flags = ['--remote-debugging-port=9222'] | 186 extra_flags = ['--remote-debugging-port=9222'] |
181 if deep_memory_profile: | 187 if deep_memory_profile: |
182 extra_flags.append('--no-sandbox') | 188 extra_flags.append('--no-sandbox') |
183 return (perf.BasePerfTest.ExtraChromeFlags(self) + extra_flags) | 189 if self._use_wpr: |
190 extra_flags.extend(ChromeEndureReplay.CHROME_FLAGS) | |
191 return perf.BasePerfTest.ExtraChromeFlags(self) + extra_flags | |
184 | 192 |
185 def _OnTimelineEvent(self, event_info): | 193 def _OnTimelineEvent(self, event_info): |
186 """Invoked by the Remote Inspector Client when a timeline event occurs. | 194 """Invoked by the Remote Inspector Client when a timeline event occurs. |
187 | 195 |
188 Args: | 196 Args: |
189 event_info: A dictionary containing raw information associated with a | 197 event_info: A dictionary containing raw information associated with a |
190 timeline event received from Chrome's remote inspector. Refer to | 198 timeline event received from Chrome's remote inspector. Refer to |
191 chrome/src/third_party/WebKit/Source/WebCore/inspector/Inspector.json | 199 chrome/src/third_party/WebKit/Source/WebCore/inspector/Inspector.json |
192 for the format of this dictionary. | 200 for the format of this dictionary. |
193 """ | 201 """ |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
533 try: | 541 try: |
534 element = self._GetElement(driver.find_element_by_xpath, xpath) | 542 element = self._GetElement(driver.find_element_by_xpath, xpath) |
535 element.click() | 543 element.click() |
536 except (selenium.common.exceptions.StaleElementReferenceException, | 544 except (selenium.common.exceptions.StaleElementReferenceException, |
537 selenium.common.exceptions.TimeoutException) as e: | 545 selenium.common.exceptions.TimeoutException) as e: |
538 logging.exception('WebDriver exception: %s' % e) | 546 logging.exception('WebDriver exception: %s' % e) |
539 return False | 547 return False |
540 | 548 |
541 return True | 549 return True |
542 | 550 |
551 def _StartReplayServerIfNecessary(self, archive_name): | |
552 """Start the Web Page Replay server if ENDURE_NO_WPR is not set. | |
553 | |
554 This method needs to be called BEFORE any connection (which are supposed | |
555 to go through the Web Page Replay server) occurs. | |
556 | |
557 Args: | |
558 archive_name: a string representing the name of the web page replay | |
559 archive. | |
560 """ | |
561 if self._use_wpr: | |
562 self._wpr_server = ChromeEndureReplay.ReplayServer(archive_name) | |
563 mode = 'Record' if self._wpr_server.is_record_mode else 'Replay' | |
564 logging.info('Starting the Web Page Replay server: in %s mode', mode) | |
565 self._wpr_server.StartServer() | |
566 logging.info('The Web Page Replay server started.') | |
Nirnimesh
2012/08/01 01:03:00
Too much logging. Please pick between this line an
fdeng1
2012/08/01 17:14:57
Done.
| |
567 | |
568 def _StopReplayServerIfNecessary(self): | |
569 """Stop the Web Page Replay server if ENDURE_NO_WPR is not set. | |
570 | |
571 This method has to be called AFTER all network connections which go | |
572 through Web Page Replay server have shut down. Otherwise the | |
573 Web Page Replay server will hang to wait for them. A good | |
574 place is to call it at the end of the teardown process. | |
575 """ | |
576 if self._use_wpr: | |
577 logging.info('Stopping The Web Page Replay server.') | |
578 self._wpr_server.StopServer() | |
579 logging.info('The Web Page Replay server stopped.') | |
580 | |
543 | 581 |
544 class ChromeEndureControlTest(ChromeEndureBaseTest): | 582 class ChromeEndureControlTest(ChromeEndureBaseTest): |
545 """Control tests for Chrome Endure.""" | 583 """Control tests for Chrome Endure.""" |
546 | 584 |
547 _WEBAPP_NAME = 'Control' | 585 _WEBAPP_NAME = 'Control' |
548 _TAB_TITLE_SUBSTRING = 'Chrome Endure Control Test' | 586 _TAB_TITLE_SUBSTRING = 'Chrome Endure Control Test' |
549 | 587 |
550 def testControlAttachDetachDOMTree(self): | 588 def testControlAttachDetachDOMTree(self): |
551 """Continually attach and detach a DOM tree from a basic document.""" | 589 """Continually attach and detach a DOM tree from a basic document.""" |
552 test_description = 'AttachDetachDOMTree' | 590 test_description = 'AttachDetachDOMTree' |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
590 test_description, lambda: scenario(driver)) | 628 test_description, lambda: scenario(driver)) |
591 | 629 |
592 | 630 |
593 class ChromeEndureGmailTest(ChromeEndureBaseTest): | 631 class ChromeEndureGmailTest(ChromeEndureBaseTest): |
594 """Long-running performance tests for Chrome using Gmail.""" | 632 """Long-running performance tests for Chrome using Gmail.""" |
595 | 633 |
596 _WEBAPP_NAME = 'Gmail' | 634 _WEBAPP_NAME = 'Gmail' |
597 _TAB_TITLE_SUBSTRING = 'Gmail' | 635 _TAB_TITLE_SUBSTRING = 'Gmail' |
598 _FRAME_XPATH = 'id("canvas_frame")' | 636 _FRAME_XPATH = 'id("canvas_frame")' |
599 | 637 |
600 def setUp(self): | 638 def _GmailSetUp(self, archive_name): |
601 ChromeEndureBaseTest.setUp(self) | 639 """Set up before each test runs.""" |
640 self._StartReplayServerIfNecessary(archive_name) | |
Nirnimesh
2012/08/01 01:03:00
I thought this was going to be done in ChromeEndur
fdeng1
2012/08/01 17:14:57
When starting a replay server, an "archive_name" n
dennis_jeffrey
2012/08/01 18:35:54
self.id(), as discussed offline
fdeng1
2012/08/01 18:37:31
I just talked to Dennis and we came up a plan to c
| |
602 | 641 |
603 # Log into a test Google account and open up Gmail. | 642 # Log into a test Google account and open up Gmail. |
604 self._LoginToGoogleAccount(account_key='test_google_account_gmail') | 643 self._LoginToGoogleAccount(account_key='test_google_account_gmail') |
605 self.NavigateToURL('http://www.gmail.com') | 644 self.NavigateToURL('http://www.gmail.com') |
606 loaded_tab_title = self.GetActiveTabTitle() | 645 loaded_tab_title = self.GetActiveTabTitle() |
607 self.assertTrue(self._TAB_TITLE_SUBSTRING in loaded_tab_title, | 646 self.assertTrue(self._TAB_TITLE_SUBSTRING in loaded_tab_title, |
608 msg='Loaded tab title does not contain "%s": "%s"' % | 647 msg='Loaded tab title does not contain "%s": "%s"' % |
609 (self._TAB_TITLE_SUBSTRING, loaded_tab_title)) | 648 (self._TAB_TITLE_SUBSTRING, loaded_tab_title)) |
610 | 649 |
611 self._driver = self.NewWebDriver() | 650 self._driver = self.NewWebDriver() |
612 # Any call to wait.until() will raise an exception if the timeout is hit. | 651 # Any call to wait.until() will raise an exception if the timeout is hit. |
613 # TODO(dennisjeffrey): Remove the need for webdriver's wait using the new | 652 # TODO(dennisjeffrey): Remove the need for webdriver's wait using the new |
614 # DOM mutation observer mechanism. | 653 # DOM mutation observer mechanism. |
615 self._wait = WebDriverWait(self._driver, timeout=60) | 654 self._wait = WebDriverWait(self._driver, timeout=60) |
616 | 655 |
617 # Wait until Gmail's 'canvas_frame' loads and the 'Inbox' link is present. | 656 # Wait until Gmail's 'canvas_frame' loads and the 'Inbox' link is present. |
618 # TODO(dennisjeffrey): Check with the Gmail team to see if there's a better | 657 # TODO(dennisjeffrey): Check with the Gmail team to see if there's a better |
619 # way to tell when the webpage is ready for user interaction. | 658 # way to tell when the webpage is ready for user interaction. |
620 self._wait.until( | 659 self._wait.until( |
621 self._SwitchToCanvasFrame) # Raises exception if the timeout is hit. | 660 self._SwitchToCanvasFrame) # Raises exception if the timeout is hit. |
622 # Wait for the inbox to appear. | 661 # Wait for the inbox to appear. |
623 self.WaitForDomNode('//a[starts-with(@title, "Inbox")]', | 662 self.WaitForDomNode('//a[starts-with(@title, "Inbox")]', |
624 frame_xpath=self._FRAME_XPATH) | 663 frame_xpath=self._FRAME_XPATH) |
625 | 664 |
665 def tearDown(self): | |
666 super(ChromeEndureGmailTest, self).tearDown() | |
667 # Stop the Web Page Replay server after all connections to WPR closed. | |
668 self._StopReplayServerIfNecessary() | |
669 | |
626 def _SwitchToCanvasFrame(self, driver): | 670 def _SwitchToCanvasFrame(self, driver): |
627 """Switch the WebDriver to Gmail's 'canvas_frame', if it's available. | 671 """Switch the WebDriver to Gmail's 'canvas_frame', if it's available. |
628 | 672 |
629 Args: | 673 Args: |
630 driver: A selenium.webdriver.remote.webdriver.WebDriver object. | 674 driver: A selenium.webdriver.remote.webdriver.WebDriver object. |
631 | 675 |
632 Returns: | 676 Returns: |
633 True, if the switch to Gmail's 'canvas_frame' is successful, or | 677 True, if the switch to Gmail's 'canvas_frame' is successful, or |
634 False if not. | 678 False if not. |
635 """ | 679 """ |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
695 else: | 739 else: |
696 logging.warning('Could not identify latency value.') | 740 logging.warning('Could not identify latency value.') |
697 | 741 |
698 def testGmailComposeDiscard(self): | 742 def testGmailComposeDiscard(self): |
699 """Continuously composes/discards an e-mail before sending. | 743 """Continuously composes/discards an e-mail before sending. |
700 | 744 |
701 This test continually composes/discards an e-mail using Gmail, and | 745 This test continually composes/discards an e-mail using Gmail, and |
702 periodically gathers performance stats that may reveal memory bloat. | 746 periodically gathers performance stats that may reveal memory bloat. |
703 """ | 747 """ |
704 test_description = 'ComposeDiscard' | 748 test_description = 'ComposeDiscard' |
749 self._GmailSetUp(test_description) | |
Nirnimesh
2012/08/01 01:03:00
Why not do this it setUp instead of calling before
fdeng1
2012/08/01 17:14:57
Please see the above comment.
On 2012/08/01 01:03
| |
705 | 750 |
706 # TODO(dennisjeffrey): Remove following line once crosbug.com/32357 is | 751 # TODO(dennisjeffrey): Remove following line once crosbug.com/32357 is |
707 # fixed. | 752 # fixed. |
708 self._test_length_sec = 60 * 60 * 5 # Run test for 5 hours. | 753 self._test_length_sec = 60 * 60 * 5 # Run test for 5 hours. |
709 | 754 |
710 def scenario(): | 755 def scenario(): |
711 # Click the "Compose" button, enter some text into the "To" field, enter | 756 # Click the "Compose" button, enter some text into the "To" field, enter |
712 # some text into the "Subject" field, then click the "Discard" button to | 757 # some text into the "Subject" field, then click the "Discard" button to |
713 # discard the message. | 758 # discard the message. |
714 compose_xpath = '//div[text()="COMPOSE"]' | 759 compose_xpath = '//div[text()="COMPOSE"]' |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
746 | 791 |
747 # TODO(dennisjeffrey): Remove this test once the Gmail team is done analyzing | 792 # TODO(dennisjeffrey): Remove this test once the Gmail team is done analyzing |
748 # the results after the test runs for a period of time. | 793 # the results after the test runs for a period of time. |
749 def testGmailComposeDiscardSleep(self): | 794 def testGmailComposeDiscardSleep(self): |
750 """Like testGmailComposeDiscard, but sleeps for 30s between iterations. | 795 """Like testGmailComposeDiscard, but sleeps for 30s between iterations. |
751 | 796 |
752 This is a temporary test requested by the Gmail team to compare against the | 797 This is a temporary test requested by the Gmail team to compare against the |
753 results from testGmailComposeDiscard above. | 798 results from testGmailComposeDiscard above. |
754 """ | 799 """ |
755 test_description = 'ComposeDiscardSleep' | 800 test_description = 'ComposeDiscardSleep' |
801 # Use the same archive_name as testGmailComposeDiscard uses. | |
802 self._GmailSetUp('ComposeDiscard') | |
756 | 803 |
757 # TODO(dennisjeffrey): Remove following line once crosbug.com/32357 is | 804 # TODO(dennisjeffrey): Remove following line once crosbug.com/32357 is |
758 # fixed. | 805 # fixed. |
759 self._test_length_sec = 60 * 60 * 5 # Run test for 5 hours. | 806 self._test_length_sec = 60 * 60 * 5 # Run test for 5 hours. |
760 | 807 |
761 def scenario(): | 808 def scenario(): |
762 # Click the "Compose" button, enter some text into the "To" field, enter | 809 # Click the "Compose" button, enter some text into the "To" field, enter |
763 # some text into the "Subject" field, then click the "Discard" button to | 810 # some text into the "Subject" field, then click the "Discard" button to |
764 # discard the message. Finally, sleep for 30 seconds. | 811 # discard the message. Finally, sleep for 30 seconds. |
765 compose_xpath = '//div[text()="COMPOSE"]' | 812 compose_xpath = '//div[text()="COMPOSE"]' |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
801 frame_xpath=self._FRAME_XPATH) | 848 frame_xpath=self._FRAME_XPATH) |
802 | 849 |
803 def testGmailAlternateThreadlistConversation(self): | 850 def testGmailAlternateThreadlistConversation(self): |
804 """Alternates between threadlist view and conversation view. | 851 """Alternates between threadlist view and conversation view. |
805 | 852 |
806 This test continually clicks between the threadlist (Inbox) and the | 853 This test continually clicks between the threadlist (Inbox) and the |
807 conversation view (e-mail message view), and periodically gathers | 854 conversation view (e-mail message view), and periodically gathers |
808 performance stats that may reveal memory bloat. | 855 performance stats that may reveal memory bloat. |
809 """ | 856 """ |
810 test_description = 'ThreadConversation' | 857 test_description = 'ThreadConversation' |
858 self._GmailSetUp(test_description) | |
811 | 859 |
812 def scenario(): | 860 def scenario(): |
813 # Click an e-mail to see the conversation view, wait 1 second, click the | 861 # Click an e-mail to see the conversation view, wait 1 second, click the |
814 # "Inbox" link to see the threadlist, wait 1 second. | 862 # "Inbox" link to see the threadlist, wait 1 second. |
815 | 863 |
816 # Find the first thread (e-mail) identified by a "span" tag that contains | 864 # Find the first thread (e-mail) identified by a "span" tag that contains |
817 # an "email" attribute. Then click it and wait for the conversation view | 865 # an "email" attribute. Then click it and wait for the conversation view |
818 # to appear (assumed to be visible when a particular div exists on the | 866 # to appear (assumed to be visible when a particular div exists on the |
819 # page). | 867 # page). |
820 thread_xpath = '//span[@email]' | 868 thread_xpath = '//span[@email]' |
(...skipping 23 matching lines...) Expand all Loading... | |
844 test_description, scenario, | 892 test_description, scenario, |
845 frame_xpath=self._FRAME_XPATH) | 893 frame_xpath=self._FRAME_XPATH) |
846 | 894 |
847 def testGmailAlternateTwoLabels(self): | 895 def testGmailAlternateTwoLabels(self): |
848 """Continuously alternates between two labels. | 896 """Continuously alternates between two labels. |
849 | 897 |
850 This test continually clicks between the "Inbox" and "Sent Mail" labels, | 898 This test continually clicks between the "Inbox" and "Sent Mail" labels, |
851 and periodically gathers performance stats that may reveal memory bloat. | 899 and periodically gathers performance stats that may reveal memory bloat. |
852 """ | 900 """ |
853 test_description = 'AlternateLabels' | 901 test_description = 'AlternateLabels' |
902 self._GmailSetUp(test_description) | |
854 | 903 |
855 def scenario(): | 904 def scenario(): |
856 # Click the "Sent Mail" label, wait for 1 second, click the "Inbox" label, | 905 # Click the "Sent Mail" label, wait for 1 second, click the "Inbox" label, |
857 # wait for 1 second. | 906 # wait for 1 second. |
858 | 907 |
859 # Click the "Sent Mail" label, then wait for the tab title to be updated | 908 # Click the "Sent Mail" label, then wait for the tab title to be updated |
860 # with the substring "sent". | 909 # with the substring "sent". |
861 sent_xpath = '//a[starts-with(text(), "Sent Mail")]' | 910 sent_xpath = '//a[starts-with(text(), "Sent Mail")]' |
862 self.WaitForDomNode(sent_xpath, frame_xpath=self._FRAME_XPATH) | 911 self.WaitForDomNode(sent_xpath, frame_xpath=self._FRAME_XPATH) |
863 sent = self._GetElement(self._driver.find_element_by_xpath, sent_xpath) | 912 sent = self._GetElement(self._driver.find_element_by_xpath, sent_xpath) |
(...skipping 22 matching lines...) Expand all Loading... | |
886 | 935 |
887 def testGmailExpandCollapseConversation(self): | 936 def testGmailExpandCollapseConversation(self): |
888 """Continuously expands/collapses all messages in a conversation. | 937 """Continuously expands/collapses all messages in a conversation. |
889 | 938 |
890 This test opens up a conversation (e-mail thread) with several messages, | 939 This test opens up a conversation (e-mail thread) with several messages, |
891 then continually alternates between the "Expand all" and "Collapse all" | 940 then continually alternates between the "Expand all" and "Collapse all" |
892 views, while periodically gathering performance stats that may reveal memory | 941 views, while periodically gathering performance stats that may reveal memory |
893 bloat. | 942 bloat. |
894 """ | 943 """ |
895 test_description = 'ExpandCollapse' | 944 test_description = 'ExpandCollapse' |
945 self._GmailSetUp(test_description) | |
896 | 946 |
897 # Enter conversation view for a particular thread. | 947 # Enter conversation view for a particular thread. |
898 thread_xpath = '//span[@email]' | 948 thread_xpath = '//span[@email]' |
899 self.WaitForDomNode(thread_xpath, frame_xpath=self._FRAME_XPATH) | 949 self.WaitForDomNode(thread_xpath, frame_xpath=self._FRAME_XPATH) |
900 thread = self._GetElement(self._driver.find_element_by_xpath, thread_xpath) | 950 thread = self._GetElement(self._driver.find_element_by_xpath, thread_xpath) |
901 thread.click() | 951 thread.click() |
902 self.WaitForDomNode('//div[text()="Click here to "]', | 952 self.WaitForDomNode('//div[text()="Click here to "]', |
903 frame_xpath=self._FRAME_XPATH) | 953 frame_xpath=self._FRAME_XPATH) |
904 | 954 |
905 def scenario(): | 955 def scenario(): |
(...skipping 30 matching lines...) Expand all Loading... | |
936 test_description, scenario, | 986 test_description, scenario, |
937 frame_xpath=self._FRAME_XPATH) | 987 frame_xpath=self._FRAME_XPATH) |
938 | 988 |
939 | 989 |
940 class ChromeEndureDocsTest(ChromeEndureBaseTest): | 990 class ChromeEndureDocsTest(ChromeEndureBaseTest): |
941 """Long-running performance tests for Chrome using Google Docs.""" | 991 """Long-running performance tests for Chrome using Google Docs.""" |
942 | 992 |
943 _WEBAPP_NAME = 'Docs' | 993 _WEBAPP_NAME = 'Docs' |
944 _TAB_TITLE_SUBSTRING = 'Google Drive' | 994 _TAB_TITLE_SUBSTRING = 'Google Drive' |
945 | 995 |
946 def setUp(self): | 996 def _DocsSetUp(self, archive_name): |
947 ChromeEndureBaseTest.setUp(self) | 997 """Set up before each test runs.""" |
998 self._StartReplayServerIfNecessary(archive_name) | |
948 | 999 |
949 # Log into a test Google account and open up Google Docs. | 1000 # Log into a test Google account and open up Google Docs. |
950 self._LoginToGoogleAccount() | 1001 self._LoginToGoogleAccount() |
951 self.NavigateToURL('http://docs.google.com') | 1002 self.NavigateToURL('http://docs.google.com') |
952 self.assertTrue( | 1003 self.assertTrue( |
953 self.WaitUntil(lambda: self._TAB_TITLE_SUBSTRING in | 1004 self.WaitUntil(lambda: self._TAB_TITLE_SUBSTRING in |
954 self.GetActiveTabTitle(), | 1005 self.GetActiveTabTitle(), |
955 timeout=60, expect_retval=True, retry_sleep=1), | 1006 timeout=60, expect_retval=True, retry_sleep=1), |
956 msg='Timed out waiting for Docs to load. Tab title is: %s' % | 1007 msg='Timed out waiting for Docs to load. Tab title is: %s' % |
957 self.GetActiveTabTitle()) | 1008 self.GetActiveTabTitle()) |
958 | 1009 |
959 self._driver = self.NewWebDriver() | 1010 self._driver = self.NewWebDriver() |
960 | 1011 |
1012 def tearDown(self): | |
1013 super(ChromeEndureDocsTest, self).tearDown() | |
1014 # Stop the Web Page Replay server after all connections to it closed. | |
1015 self._StopReplayServerIfNecessary() | |
1016 | |
961 def testDocsAlternatelyClickLists(self): | 1017 def testDocsAlternatelyClickLists(self): |
962 """Alternates between two different document lists. | 1018 """Alternates between two different document lists. |
963 | 1019 |
964 This test alternately clicks the "Shared with me" and "My Drive" buttons in | 1020 This test alternately clicks the "Shared with me" and "My Drive" buttons in |
965 Google Docs, and periodically gathers performance stats that may reveal | 1021 Google Docs, and periodically gathers performance stats that may reveal |
966 memory bloat. | 1022 memory bloat. |
967 """ | 1023 """ |
968 test_description = 'AlternateLists' | 1024 test_description = 'AlternateLists' |
1025 self._DocsSetUp(test_description) | |
969 | 1026 |
970 def scenario(): | 1027 def scenario(): |
971 # Click the "Shared with me" button, wait for 1 second, click the | 1028 # Click the "Shared with me" button, wait for 1 second, click the |
972 # "My Drive" button, wait for 1 second. | 1029 # "My Drive" button, wait for 1 second. |
973 | 1030 |
974 # Click the "Shared with me" button and wait for a div to appear. | 1031 # Click the "Shared with me" button and wait for a div to appear. |
975 if not self._ClickElementByXpath( | 1032 if not self._ClickElementByXpath( |
976 self._driver, '//span[starts-with(text(), "Shared with me")]'): | 1033 self._driver, '//span[starts-with(text(), "Shared with me")]'): |
977 self._num_errors += 1 | 1034 self._num_errors += 1 |
978 self.WaitForDomNode('//div[text()="Share date"]') | 1035 self.WaitForDomNode('//div[text()="Share date"]') |
(...skipping 18 matching lines...) Expand all Loading... | |
997 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, | 1054 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, |
998 test_description, scenario) | 1055 test_description, scenario) |
999 | 1056 |
1000 | 1057 |
1001 class ChromeEndurePlusTest(ChromeEndureBaseTest): | 1058 class ChromeEndurePlusTest(ChromeEndureBaseTest): |
1002 """Long-running performance tests for Chrome using Google Plus.""" | 1059 """Long-running performance tests for Chrome using Google Plus.""" |
1003 | 1060 |
1004 _WEBAPP_NAME = 'Plus' | 1061 _WEBAPP_NAME = 'Plus' |
1005 _TAB_TITLE_SUBSTRING = 'Google+' | 1062 _TAB_TITLE_SUBSTRING = 'Google+' |
1006 | 1063 |
1007 def setUp(self): | 1064 def _PlusSetUp(self, archive_name): |
1008 ChromeEndureBaseTest.setUp(self) | 1065 """Set up before each test runs.""" |
1066 self._StartReplayServerIfNecessary(archive_name) | |
1009 | 1067 |
1010 # Log into a test Google account and open up Google Plus. | 1068 # Log into a test Google account and open up Google Plus. |
1011 self._LoginToGoogleAccount() | 1069 self._LoginToGoogleAccount() |
1012 self.NavigateToURL('http://plus.google.com') | 1070 self.NavigateToURL('http://plus.google.com') |
1013 loaded_tab_title = self.GetActiveTabTitle() | 1071 loaded_tab_title = self.GetActiveTabTitle() |
1014 self.assertTrue(self._TAB_TITLE_SUBSTRING in loaded_tab_title, | 1072 self.assertTrue(self._TAB_TITLE_SUBSTRING in loaded_tab_title, |
1015 msg='Loaded tab title does not contain "%s": "%s"' % | 1073 msg='Loaded tab title does not contain "%s": "%s"' % |
1016 (self._TAB_TITLE_SUBSTRING, loaded_tab_title)) | 1074 (self._TAB_TITLE_SUBSTRING, loaded_tab_title)) |
1017 | 1075 |
1018 self._driver = self.NewWebDriver() | 1076 self._driver = self.NewWebDriver() |
1019 | 1077 |
1078 def tearDown(self): | |
1079 super(ChromeEndurePlusTest, self).tearDown() | |
1080 # Stop the Web Page Replay server after all connections to it closed. | |
1081 self._StopReplayServerIfNecessary() | |
1082 | |
1020 def testPlusAlternatelyClickStreams(self): | 1083 def testPlusAlternatelyClickStreams(self): |
1021 """Alternates between two different streams. | 1084 """Alternates between two different streams. |
1022 | 1085 |
1023 This test alternately clicks the "Friends" and "Family" buttons using | 1086 This test alternately clicks the "Friends" and "Family" buttons using |
1024 Google Plus, and periodically gathers performance stats that may reveal | 1087 Google Plus, and periodically gathers performance stats that may reveal |
1025 memory bloat. | 1088 memory bloat. |
1026 """ | 1089 """ |
1027 test_description = 'AlternateStreams' | 1090 test_description = 'AlternateStreams' |
1091 self._PlusSetUp(test_description) | |
1028 | 1092 |
1029 # TODO(dennisjeffrey): Remove following line once crosbug.com/32357 is | 1093 # TODO(dennisjeffrey): Remove following line once crosbug.com/32357 is |
1030 # fixed. | 1094 # fixed. |
1031 self._test_length_sec = 60 * 60 * 3 # Run test for 3 hours. | 1095 self._test_length_sec = 60 * 60 * 3 # Run test for 3 hours. |
1032 | 1096 |
1033 def scenario(): | 1097 def scenario(): |
1034 # Click the "Friends" button, wait for 1 second, click the "Family" | 1098 # Click the "Friends" button, wait for 1 second, click the "Family" |
1035 # button, wait for 1 second. | 1099 # button, wait for 1 second. |
1036 | 1100 |
1037 # Click the "Friends" button and wait for a resulting div to appear. | 1101 # Click the "Friends" button and wait for a resulting div to appear. |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1117 except (pyauto_errors.JSONInterfaceError, | 1181 except (pyauto_errors.JSONInterfaceError, |
1118 pyauto_errors.JavascriptRuntimeError): | 1182 pyauto_errors.JavascriptRuntimeError): |
1119 self._num_errors += 1 | 1183 self._num_errors += 1 |
1120 | 1184 |
1121 time.sleep(1) | 1185 time.sleep(1) |
1122 | 1186 |
1123 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, | 1187 self._RunEndureTest(self._WEBAPP_NAME, self._TAB_TITLE_SUBSTRING, |
1124 test_description, scenario) | 1188 test_description, scenario) |
1125 | 1189 |
1126 | 1190 |
1191 class ChromeEndureReplay(object): | |
1192 """Run Chrome Endure tests with network simulation via Web Page Replay.""" | |
1193 | |
1194 _PATHS = { | |
1195 'archive': | |
1196 'src/chrome/test/data/pyauto_private/webpagereplay/{archive_name}.wpr', | |
1197 'scripts': | |
1198 'src/chrome/test/data/chrome_endure/webpagereplay/wpr_deterministic.js', | |
1199 } | |
1200 CHROME_FLAGS = webpagereplay.CHROME_FLAGS | |
1201 | |
1202 @classmethod | |
1203 def Path(cls, key, **kwargs): | |
1204 return perf.FormatChromePath(cls._PATHS[key], **kwargs) | |
1205 | |
1206 @classmethod | |
1207 def ReplayServer(cls, archive_name): | |
1208 """Creat a replay server.""" | |
1209 # Inject customized scripts for Google webapps. | |
1210 # See the java script file for details. | |
1211 scripts = cls.Path('scripts') | |
1212 if not os.path.exists(scripts): | |
1213 raise webpagereplay.ReplayNotFoundError('injected scripts', scripts) | |
1214 replay_options = ['--inject_scripts', scripts] | |
1215 archive_path = cls.Path('archive', archive_name=archive_name) | |
1216 return webpagereplay.ReplayServer(archive_path, replay_options) | |
1217 | |
1218 | |
1127 if __name__ == '__main__': | 1219 if __name__ == '__main__': |
1128 pyauto_functional.Main() | 1220 pyauto_functional.Main() |
OLD | NEW |