1 # Copyright 2014 The Chromium Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import os 6 import re 7 import shutil 8 import sys 9 import StringIO 10 import tempfile 11 import unittest 12 13 from telemetry import benchmark 14 from telemetry import story 15 from telemetry.core import exceptions 16 from telemetry.core import util 17 from telemetry import decorators 18 from telemetry.internal.browser import browser_finder 19 from telemetry.internal.browser import user_agent 20 from telemetry.internal.results import results_options 21 from telemetry.internal import story_runner 22 from telemetry.internal.testing.page_sets import example_domain 23 from telemetry.internal.util import exception_formatter 24 from telemetry.page import page as page_module 25 from telemetry.page import page_test 26 from telemetry.page import shared_page_state 27 from telemetry.util import image_util 28 from telemetry.testing import fakes 29 from telemetry.testing import options_for_unittests 30 from telemetry.testing import system_stub 31 32 33 SIMPLE_CREDENTIALS_STRING = """ 34 { 35 "test": { 36 "username": "example", 37 "password": "asdf" 38 } 39 } 40 """ 41 42 43 class DummyTest(page_test.PageTest): 44 45 def ValidateAndMeasurePage(self, *_): 46 pass 47 48 49 def SetUpStoryRunnerArguments(options): 50 parser = options.CreateParser() 51 story_runner.AddCommandLineArgs(parser) 52 options.MergeDefaultValues(parser.get_default_values()) 53 story_runner.ProcessCommandLineArgs(parser, options) 54 55 56 class EmptyMetadataForTest(benchmark.BenchmarkMetadata): 57 58 def __init__(self): 59 super(EmptyMetadataForTest, self).__init__('') 60 61 62 class StubCredentialsBackend(object): 63 64 def __init__(self, login_return_value): 65 self.did_get_login = False 66 self.did_get_login_no_longer_needed = False 67 self.login_return_value = login_return_value 68 69 @property 70 def credentials_type(self): 71 return 'test' 72 73 def LoginNeeded(self, *_): 74 self.did_get_login = True 75 return self.login_return_value 76 77 def LoginNoLongerNeeded(self, _): 78 self.did_get_login_no_longer_needed = True 79 80 81 def GetSuccessfulPageRuns(results): 82 return [run for run in results.all_page_runs if run.ok or run.skipped] 83 84 85 def CaptureStderr(func, output_buffer): 86 def wrapper(*args, **kwargs): 87 original_stderr, sys.stderr = sys.stderr, output_buffer 88 try: 89 return func(*args, **kwargs) 90 finally: 91 sys.stderr = original_stderr 92 return wrapper 93 94 95 # TODO: remove test cases that use real browsers and replace with a 96 # story_runner or shared_page_state unittest that tests the same logic. 97 class ActualPageRunEndToEndTests(unittest.TestCase): 98 # TODO(nduca): Move the basic "test failed, test succeeded" tests from 99 # page_test_unittest to here. 100 101 def setUp(self): 102 self._story_runner_logging_stub = None 103 self._formatted_exception_buffer = StringIO.StringIO() 104 self._original_formatter = exception_formatter.PrintFormattedException 105 106 def tearDown(self): 107 self.RestoreExceptionFormatter() 108 109 def CaptureFormattedException(self): 110 exception_formatter.PrintFormattedException = CaptureStderr( 111 exception_formatter.PrintFormattedException, 112 self._formatted_exception_buffer) 113 self._story_runner_logging_stub = system_stub.Override( 114 story_runner, ['logging']) 115 116 @property 117 def formatted_exception(self): 118 return self._formatted_exception_buffer.getvalue() 119 120 def RestoreExceptionFormatter(self): 121 exception_formatter.PrintFormattedException = self._original_formatter 122 if self._story_runner_logging_stub: 123 self._story_runner_logging_stub.Restore() 124 self._story_runner_logging_stub = None 125 126 def assertFormattedExceptionIsEmpty(self): 127 self.longMessage = False 128 self.assertEquals( 129 '', self.formatted_exception, 130 msg='Expected empty formatted exception: actual=%s' % '\n > '.join( 131 self.formatted_exception.split('\n'))) 132 133 def assertFormattedExceptionOnlyHas(self, expected_exception_name): 134 self.longMessage = True 135 actual_exception_names = re.findall(r'^Traceback.*?^(\w+)', 136 self.formatted_exception, 137 re.DOTALL | re.MULTILINE) 138 self.assertEquals([expected_exception_name], actual_exception_names, 139 msg='Full formatted exception: %s' % '\n > '.join( 140 self.formatted_exception.split('\n'))) 141 142 def testRaiseBrowserGoneExceptionFromRestartBrowserBeforeEachPage(self): 143 self.CaptureFormattedException() 144 story_set = story.StorySet() 145 story_set.AddStory(page_module.Page( 146 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir())) 147 story_set.AddStory(page_module.Page( 148 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir())) 149 story_set.AddStory(page_module.Page( 150 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir())) 151 152 class Test(page_test.PageTest): 153 154 def __init__(self, *args): 155 super(Test, self).__init__( 156 *args, needs_browser_restart_after_each_page=True) 157 self.run_count = 0 158 159 def RestartBrowserBeforeEachPage(self): 160 # This will only be called twice with 3 pages. 161 old_run_count = self.run_count 162 self.run_count += 1 163 if old_run_count == 1: 164 raise exceptions.BrowserGoneException(None) 165 return self._needs_browser_restart_after_each_page 166 167 def ValidateAndMeasurePage(self, page, tab, results): 168 pass 169 170 options = options_for_unittests.GetCopy() 171 options.output_formats = ['none'] 172 options.suppress_gtest_report = True 173 test = Test() 174 SetUpStoryRunnerArguments(options) 175 results = results_options.CreateResults(EmptyMetadataForTest(), options) 176 story_runner.Run(test, story_set, options, results) 177 self.assertEquals(2, test.run_count) 178 self.assertEquals(2, len(GetSuccessfulPageRuns(results))) 179 self.assertEquals(1, len(results.failures)) 180 self.assertFormattedExceptionIsEmpty() 181 182 def testNeedsBrowserRestartAfterEachPage(self): 183 self.CaptureFormattedException() 184 story_set = story.StorySet() 185 story_set.AddStory(page_module.Page( 186 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir())) 187 story_set.AddStory(page_module.Page( 188 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir())) 189 190 class Test(page_test.PageTest): 191 192 def __init__(self, *args, **kwargs): 193 super(Test, self).__init__(*args, **kwargs) 194 self.browser_starts = 0 195 196 def DidStartBrowser(self, *args): 197 super(Test, self).DidStartBrowser(*args) 198 self.browser_starts += 1 199 200 def ValidateAndMeasurePage(self, page, tab, results): 201 pass 202 203 options = options_for_unittests.GetCopy() 204 options.output_formats = ['none'] 205 options.suppress_gtest_report = True 206 test = Test(needs_browser_restart_after_each_page=True) 207 SetUpStoryRunnerArguments(options) 208 results = results_options.CreateResults(EmptyMetadataForTest(), options) 209 story_runner.Run(test, story_set, options, results) 210 self.assertEquals(2, len(GetSuccessfulPageRuns(results))) 211 self.assertEquals(2, test.browser_starts) 212 self.assertFormattedExceptionIsEmpty() 213 214 def testCredentialsWhenLoginFails(self): 215 self.CaptureFormattedException() 216 credentials_backend = StubCredentialsBackend(login_return_value=False) 217 did_run = self.runCredentialsTest(credentials_backend) 218 assert credentials_backend.did_get_login 219 assert not credentials_backend.did_get_login_no_longer_needed 220 assert not did_run 221 self.assertFormattedExceptionIsEmpty() 222 223 def testCredentialsWhenLoginSucceeds(self): 224 credentials_backend = StubCredentialsBackend(login_return_value=True) 225 did_run = self.runCredentialsTest(credentials_backend) 226 assert credentials_backend.did_get_login 227 assert credentials_backend.did_get_login_no_longer_needed 228 assert did_run 229 230 def runCredentialsTest(self, credentials_backend): 231 story_set = story.StorySet() 232 did_run = [False] 233 234 try: 235 with tempfile.NamedTemporaryFile(delete=False) as f: 236 page = page_module.Page( 237 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir(), 238 credentials_path=f.name) 239 page.credentials = "test" 240 story_set.AddStory(page) 241 242 f.write(SIMPLE_CREDENTIALS_STRING) 243 244 class TestThatInstallsCredentialsBackend(page_test.PageTest): 245 246 def __init__(self, credentials_backend): 247 super(TestThatInstallsCredentialsBackend, self).__init__() 248 self._credentials_backend = credentials_backend 249 250 def DidStartBrowser(self, browser): 251 browser.credentials.AddBackend(self._credentials_backend) 252 253 def ValidateAndMeasurePage(self, *_): 254 did_run[0] = True 255 256 test = TestThatInstallsCredentialsBackend(credentials_backend) 257 options = options_for_unittests.GetCopy() 258 options.output_formats = ['none'] 259 options.suppress_gtest_report = True 260 SetUpStoryRunnerArguments(options) 261 results = results_options.CreateResults(EmptyMetadataForTest(), options) 262 story_runner.Run(test, story_set, options, results) 263 finally: 264 os.remove(f.name) 265 266 return did_run[0] 267 268 @decorators.Disabled('chromeos') # crbug.com/483212 269 def testUserAgent(self): 270 story_set = story.StorySet() 271 page = page_module.Page( 272 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir(), 273 shared_page_state_class=shared_page_state.SharedTabletPageState) 274 story_set.AddStory(page) 275 276 class TestUserAgent(page_test.PageTest): 277 def ValidateAndMeasurePage(self, page, tab, results): 278 del page, results # unused 279 actual_user_agent = tab.EvaluateJavaScript('window.navigator.userAgent') 280 expected_user_agent = user_agent.UA_TYPE_MAPPING['tablet'] 281 assert actual_user_agent.strip() == expected_user_agent 282 283 # This is so we can check later that the test actually made it into this 284 # function. Previously it was timing out before even getting here, which 285 # should fail, but since it skipped all the asserts, it slipped by. 286 self.hasRun = True # pylint: disable=attribute-defined-outside-init 287 288 test = TestUserAgent() 289 options = options_for_unittests.GetCopy() 290 options.output_formats = ['none'] 291 options.suppress_gtest_report = True 292 SetUpStoryRunnerArguments(options) 293 results = results_options.CreateResults(EmptyMetadataForTest(), options) 294 story_runner.Run(test, story_set, options, results) 295 296 self.assertTrue(hasattr(test, 'hasRun') and test.hasRun) 297 298 # Ensure that story_runner forces exactly 1 tab before running a page. 299 @decorators.Enabled('has tabs') 300 def testOneTab(self): 301 story_set = story.StorySet() 302 page = page_module.Page( 303 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir()) 304 story_set.AddStory(page) 305 306 class TestOneTab(page_test.PageTest): 307 308 def DidStartBrowser(self, browser): 309 browser.tabs.New() 310 311 def ValidateAndMeasurePage(self, page, tab, results): 312 del page, results # unused 313 assert len(tab.browser.tabs) == 1 314 315 test = TestOneTab() 316 options = options_for_unittests.GetCopy() 317 options.output_formats = ['none'] 318 options.suppress_gtest_report = True 319 SetUpStoryRunnerArguments(options) 320 results = results_options.CreateResults(EmptyMetadataForTest(), options) 321 story_runner.Run(test, story_set, options, results) 322 323 # Ensure that story_runner allows >1 tab for multi-tab test. 324 @decorators.Enabled('has tabs') 325 def testMultipleTabsOkayForMultiTabTest(self): 326 story_set = story.StorySet() 327 page = page_module.Page( 328 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir()) 329 story_set.AddStory(page) 330 331 class TestMultiTabs(page_test.PageTest): 332 def TabForPage(self, page, browser): 333 del page # unused 334 return browser.tabs.New() 335 336 def ValidateAndMeasurePage(self, page, tab, results): 337 del page, results # unused 338 assert len(tab.browser.tabs) == 2 339 340 test = TestMultiTabs() 341 options = options_for_unittests.GetCopy() 342 options.output_formats = ['none'] 343 options.suppress_gtest_report = True 344 SetUpStoryRunnerArguments(options) 345 results = results_options.CreateResults(EmptyMetadataForTest(), options) 346 story_runner.Run(test, story_set, options, results) 347 348 # Ensure that story_runner allows the test to customize the browser 349 # before it launches. 350 def testBrowserBeforeLaunch(self): 351 story_set = story.StorySet() 352 page = page_module.Page( 353 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir()) 354 story_set.AddStory(page) 355 356 class TestBeforeLaunch(page_test.PageTest): 357 358 def __init__(self): 359 super(TestBeforeLaunch, self).__init__() 360 self._did_call_will_start = False 361 self._did_call_did_start = False 362 363 def WillStartBrowser(self, platform): 364 self._did_call_will_start = True 365 # TODO(simonjam): Test that the profile is available. 366 367 def DidStartBrowser(self, browser): 368 assert self._did_call_will_start 369 self._did_call_did_start = True 370 371 def ValidateAndMeasurePage(self, *_): 372 assert self._did_call_did_start 373 374 test = TestBeforeLaunch() 375 options = options_for_unittests.GetCopy() 376 options.output_formats = ['none'] 377 options.suppress_gtest_report = True 378 SetUpStoryRunnerArguments(options) 379 results = results_options.CreateResults(EmptyMetadataForTest(), options) 380 story_runner.Run(test, story_set, options, results) 381 382 def testRunPageWithStartupUrl(self): 383 num_times_browser_closed = [0] 384 385 class TestSharedState(shared_page_state.SharedPageState): 386 387 def _StopBrowser(self): 388 super(TestSharedState, self)._StopBrowser() 389 num_times_browser_closed[0] += 1 390 391 story_set = story.StorySet() 392 page = page_module.Page( 393 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir(), 394 startup_url='about:blank', shared_page_state_class=TestSharedState) 395 story_set.AddStory(page) 396 397 class Measurement(page_test.PageTest): 398 399 def __init__(self): 400 super(Measurement, self).__init__() 401 402 def ValidateAndMeasurePage(self, page, tab, results): 403 del page, tab, results # not used 404 405 options = options_for_unittests.GetCopy() 406 options.page_repeat = 2 407 options.output_formats = ['none'] 408 options.suppress_gtest_report = True 409 if not browser_finder.FindBrowser(options): 410 return 411 test = Measurement() 412 SetUpStoryRunnerArguments(options) 413 results = results_options.CreateResults(EmptyMetadataForTest(), options) 414 story_runner.Run(test, story_set, options, results) 415 self.assertEquals('about:blank', options.browser_options.startup_url) 416 # _StopBrowser should be called 2 times: 417 # 1. browser restarts after page 1 run 418 # 2. in the TearDownState after all the pages have run. 419 self.assertEquals(num_times_browser_closed[0], 2) 420 421 # Ensure that story_runner calls cleanUp when a page run fails. 422 def testCleanUpPage(self): 423 story_set = story.StorySet() 424 page = page_module.Page( 425 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir()) 426 story_set.AddStory(page) 427 428 class Test(page_test.PageTest): 429 430 def __init__(self): 431 super(Test, self).__init__() 432 self.did_call_clean_up = False 433 434 def ValidateAndMeasurePage(self, *_): 435 raise page_test.Failure 436 437 def DidRunPage(self, platform): 438 del platform # unused 439 self.did_call_clean_up = True 440 441 test = Test() 442 options = options_for_unittests.GetCopy() 443 options.output_formats = ['none'] 444 options.suppress_gtest_report = True 445 SetUpStoryRunnerArguments(options) 446 results = results_options.CreateResults(EmptyMetadataForTest(), options) 447 story_runner.Run(test, story_set, options, results) 448 assert test.did_call_clean_up 449 450 # Ensure skipping the test if shared state cannot be run on the browser. 451 def testSharedPageStateCannotRunOnBrowser(self): 452 story_set = story.StorySet() 453 454 class UnrunnableSharedState(shared_page_state.SharedPageState): 455 def CanRunOnBrowser(self, browser_info, page): 456 del browser_info, page # unused 457 return False 458 459 def ValidateAndMeasurePage(self, _): 460 pass 461 462 story_set.AddStory(page_module.Page( 463 url='file://blank.html', page_set=story_set, 464 base_dir=util.GetUnittestDataDir(), 465 shared_page_state_class=UnrunnableSharedState)) 466 467 class Test(page_test.PageTest): 468 469 def __init__(self, *args, **kwargs): 470 super(Test, self).__init__(*args, **kwargs) 471 self.will_navigate_to_page_called = False 472 473 def ValidateAndMeasurePage(self, *args): 474 del args # unused 475 raise Exception('Exception should not be thrown') 476 477 def WillNavigateToPage(self, page, tab): 478 del page, tab # unused 479 self.will_navigate_to_page_called = True 480 481 test = Test() 482 options = options_for_unittests.GetCopy() 483 options.output_formats = ['none'] 484 options.suppress_gtest_report = True 485 SetUpStoryRunnerArguments(options) 486 results = results_options.CreateResults(EmptyMetadataForTest(), options) 487 story_runner.Run(test, story_set, options, results) 488 self.assertFalse(test.will_navigate_to_page_called) 489 self.assertEquals(1, len(GetSuccessfulPageRuns(results))) 490 self.assertEquals(1, len(results.skipped_values)) 491 self.assertEquals(0, len(results.failures)) 492 493 def testRunPageWithProfilingFlag(self): 494 story_set = story.StorySet() 495 story_set.AddStory(page_module.Page( 496 'file://blank.html', story_set, base_dir=util.GetUnittestDataDir())) 497 498 class Measurement(page_test.PageTest): 499 500 def ValidateAndMeasurePage(self, page, tab, results): 501 pass 502 503 options = options_for_unittests.GetCopy() 504 options.output_formats = ['none'] 505 options.suppress_gtest_report = True 506 options.reset_results = None 507 options.upload_results = None 508 options.results_label = None 509 options.output_dir = tempfile.mkdtemp() 510 options.profiler = 'trace' 511 try: 512 SetUpStoryRunnerArguments(options) 513 results = results_options.CreateResults(EmptyMetadataForTest(), options) 514 story_runner.Run(Measurement(), story_set, options, results) 515 self.assertEquals(1, len(GetSuccessfulPageRuns(results))) 516 self.assertEquals(0, len(results.failures)) 517 self.assertEquals(0, len(results.all_page_specific_values)) 518 self.assertTrue(os.path.isfile( 519 os.path.join(options.output_dir, 'blank_html.zip'))) 520 finally: 521 shutil.rmtree(options.output_dir) 522 523 def _RunPageTestThatRaisesAppCrashException(self, test, max_failures): 524 class TestPage(page_module.Page): 525 526 def RunNavigateSteps(self, _): 527 raise exceptions.AppCrashException 528 529 story_set = story.StorySet() 530 for _ in range(5): 531 story_set.AddStory( 532 TestPage('file://blank.html', story_set, 533 base_dir=util.GetUnittestDataDir())) 534 options = options_for_unittests.GetCopy() 535 options.output_formats = ['none'] 536 options.suppress_gtest_report = True 537 SetUpStoryRunnerArguments(options) 538 results = results_options.CreateResults(EmptyMetadataForTest(), options) 539 story_runner.Run(test, story_set, options, results, 540 max_failures=max_failures) 541 return results 542 543 def testSingleTabMeansCrashWillCauseFailureValue(self): 544 self.CaptureFormattedException() 545 546 class SingleTabTest(page_test.PageTest): 547 # Test is not multi-tab because it does not override TabForPage. 548 549 def ValidateAndMeasurePage(self, *_): 550 pass 551 552 test = SingleTabTest() 553 results = self._RunPageTestThatRaisesAppCrashException( 554 test, max_failures=1) 555 self.assertEquals([], GetSuccessfulPageRuns(results)) 556 self.assertEquals(2, len(results.failures)) # max_failures + 1 557 self.assertFormattedExceptionIsEmpty() 558 559 @decorators.Enabled('has tabs') 560 def testMultipleTabsMeansCrashRaises(self): 561 self.CaptureFormattedException() 562 563 class MultipleTabsTest(page_test.PageTest): 564 # Test *is* multi-tab because it overrides TabForPage. 565 566 def TabForPage(self, page, browser): 567 return browser.tabs.New() 568 569 def ValidateAndMeasurePage(self, *_): 570 pass 571 572 test = MultipleTabsTest() 573 with self.assertRaises(page_test.MultiTabTestAppCrashError): 574 self._RunPageTestThatRaisesAppCrashException(test, max_failures=1) 575 self.assertFormattedExceptionOnlyHas('AppCrashException') 576 577 def testWebPageReplay(self): 578 story_set = example_domain.ExampleDomainPageSet() 579 body = [] 580 581 class TestWpr(page_test.PageTest): 582 def ValidateAndMeasurePage(self, page, tab, results): 583 del page, results # unused 584 body.append(tab.EvaluateJavaScript('document.body.innerText')) 585 586 def DidRunPage(self, platform): 587 # Force the replay server to restart between pages; this verifies that 588 # the restart mechanism works. 589 platform.network_controller.StopReplay() 590 591 test = TestWpr() 592 options = options_for_unittests.GetCopy() 593 options.output_formats = ['none'] 594 options.suppress_gtest_report = True 595 SetUpStoryRunnerArguments(options) 596 results = results_options.CreateResults(EmptyMetadataForTest(), options) 597 598 story_runner.Run(test, story_set, options, results) 599 600 self.longMessage = True 601 self.assertIn('Example Domain', body[0], 602 msg='URL: %s' % story_set.stories[0].url) 603 self.assertIn('Example Domain', body[1], 604 msg='URL: %s' % story_set.stories[1].url) 605 606 self.assertEquals(2, len(GetSuccessfulPageRuns(results))) 607 self.assertEquals(0, len(results.failures)) 608 609 def testScreenShotTakenForFailedPage(self): 610 self.CaptureFormattedException() 611 platform_screenshot_supported = [False] 612 tab_screenshot_supported = [False] 613 chrome_version_screen_shot = [None] 614 615 class FailingTestPage(page_module.Page): 616 617 def RunNavigateSteps(self, action_runner): 618 action_runner.Navigate(self._url) 619 platform_screenshot_supported[0] = ( 620 action_runner.tab.browser.platform.CanTakeScreenshot) 621 tab_screenshot_supported[0] = action_runner.tab.screenshot_supported 622 if not platform_screenshot_supported[0] and tab_screenshot_supported[0]: 623 chrome_version_screen_shot[0] = action_runner.tab.Screenshot() 624 raise exceptions.AppCrashException 625 626 story_set = story.StorySet() 627 story_set.AddStory(page_module.Page('file://blank.html', story_set)) 628 failing_page = FailingTestPage('chrome://version', story_set) 629 story_set.AddStory(failing_page) 630 options = options_for_unittests.GetCopy() 631 options.output_formats = ['none'] 632 options.browser_options.take_screenshot_for_failed_page = True 633 options.suppress_gtest_report = True 634 SetUpStoryRunnerArguments(options) 635 results = results_options.CreateResults(EmptyMetadataForTest(), options) 636 story_runner.Run(DummyTest(), story_set, options, results, 637 max_failures=2) 638 self.assertEquals(1, len(results.failures)) 639 if not platform_screenshot_supported[0] and tab_screenshot_supported[0]: 640 self.assertEquals(1, len(results.pages_to_profiling_files)) 641 self.assertIn(failing_page, 642 results.pages_to_profiling_files) 643 screenshot_file_path = ( 644 results.pages_to_profiling_files[failing_page][0].GetAbsPath()) 645 try: 646 actual_screenshot = image_util.FromPngFile(screenshot_file_path) 647 self.assertEquals(image_util.Pixels(chrome_version_screen_shot[0]), 648 image_util.Pixels(actual_screenshot)) 649 finally: # Must clean up screenshot file if exists. 650 os.remove(screenshot_file_path) 651 652 def testNoProfilingFilesCreatedForPageByDefault(self): 653 self.CaptureFormattedException() 654 655 class FailingTestPage(page_module.Page): 656 657 def RunNavigateSteps(self, action_runner): 658 action_runner.Navigate(self._url) 659 raise exceptions.AppCrashException 660 661 story_set = story.StorySet() 662 story_set.AddStory(page_module.Page('file://blank.html', story_set)) 663 failing_page = FailingTestPage('chrome://version', story_set) 664 story_set.AddStory(failing_page) 665 options = options_for_unittests.GetCopy() 666 options.output_formats = ['none'] 667 options.suppress_gtest_report = True 668 SetUpStoryRunnerArguments(options) 669 results = results_options.CreateResults(EmptyMetadataForTest(), options) 670 story_runner.Run(DummyTest(), story_set, options, results, 671 max_failures=2) 672 self.assertEquals(1, len(results.failures)) 673 self.assertEquals(0, len(results.pages_to_profiling_files)) 674 675 676 class FakePageRunEndToEndTests(unittest.TestCase): 677 678 def setUp(self): 679 self.options = fakes.CreateBrowserFinderOptions() 680 self.options.output_formats = ['none'] 681 self.options.suppress_gtest_report = True 682 SetUpStoryRunnerArguments(self.options) 683 684 def testNoScreenShotTakenForFailedPageDueToNoSupport(self): 685 self.options.browser_options.take_screenshot_for_failed_page = True 686 687 class FailingTestPage(page_module.Page): 688 689 def RunNavigateSteps(self, action_runner): 690 raise exceptions.AppCrashException 691 692 story_set = story.StorySet() 693 story_set.AddStory(page_module.Page('file://blank.html', story_set)) 694 failing_page = FailingTestPage('chrome://version', story_set) 695 story_set.AddStory(failing_page) 696 results = results_options.CreateResults( 697 EmptyMetadataForTest(), self.options) 698 story_runner.Run(DummyTest(), story_set, self.options, results, 699 max_failures=2) 700 self.assertEquals(1, len(results.failures)) 701 self.assertEquals(0, len(results.pages_to_profiling_files)) 702 703 def testScreenShotTakenForFailedPageOnSupportedPlatform(self): 704 fake_platform = self.options.fake_possible_browser.returned_browser.platform 705 expected_png_base64 = """ 706 iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91 707 JpzAAAAFklEQVR4Xg3EAQ0AAABAMP1LY3YI7l8l6A 708 T8tgwbJAAAAABJRU5ErkJggg== 709 """ 710 fake_platform.screenshot_png_data = expected_png_base64 711 self.options.browser_options.take_screenshot_for_failed_page = True 712 713 class FailingTestPage(page_module.Page): 714 715 def RunNavigateSteps(self, action_runner): 716 raise exceptions.AppCrashException 717 story_set = story.StorySet() 718 story_set.AddStory(page_module.Page('file://blank.html', story_set)) 719 failing_page = FailingTestPage('chrome://version', story_set) 720 story_set.AddStory(failing_page) 721 722 results = results_options.CreateResults( 723 EmptyMetadataForTest(), self.options) 724 story_runner.Run(DummyTest(), story_set, self.options, results, 725 max_failures=2) 726 self.assertEquals(1, len(results.failures)) 727 self.assertEquals(1, len(results.pages_to_profiling_files)) 728 self.assertIn(failing_page, 729 results.pages_to_profiling_files) 730 screenshot_file_path = ( 731 results.pages_to_profiling_files[failing_page][0].GetAbsPath()) 732 try: 733 actual_screenshot_img = image_util.FromPngFile(screenshot_file_path) 734 self.assertTrue(image_util.AreEqual( 735 image_util.FromBase64Png(expected_png_base64), 736 actual_screenshot_img)) 737 finally: # Must clean up screenshot file if exists. 738 os.remove(screenshot_file_path) 739