def test_managed_webdriver_with_explicit_chrome_version(self): popen_calls = self.exit_stack.enter_context(self.swap_popen()) self.exit_stack.enter_context(self.swap(common, 'OS_NAME', 'Linux')) self.exit_stack.enter_context( self.swap_with_checks(subprocess, 'check_call', lambda _: None, expected_args=[ ([ common.NODE_BIN_PATH, common.WEBDRIVER_MANAGER_BIN_PATH, 'update', '--versions.chrome', '123' ], ), ])) self.exit_stack.enter_context( self.swap_with_checks(common, 'wait_for_port_to_be_in_use', lambda _: None, expected_args=[(4444, )])) self.exit_stack.enter_context( servers.managed_webdriver_server(chrome_version='123')) self.exit_stack.close() self.assertEqual(len(popen_calls), 1) self.assertEqual( popen_calls[0].program_args, '%s %s start --versions.chrome 123 --quiet --standalone' % (common.NODE_BIN_PATH, common.WEBDRIVER_MANAGER_BIN_PATH))
def test_managed_webdriver_on_non_mac_os(self): popen_calls = self.exit_stack.enter_context(self.swap_popen()) self.exit_stack.enter_context(self.swap(common, 'OS_NAME', 'Linux')) self.exit_stack.enter_context( self.swap_to_always_return(subprocess, 'check_call')) self.exit_stack.enter_context( self.swap_with_checks(subprocess, 'check_output', lambda _: b'1.2.3.45', expected_args=[ (['google-chrome', '--version'], ), ])) self.exit_stack.enter_context( self.swap_with_checks( utils, 'url_open', lambda _: mock.Mock(read=lambda: b'1.2.3'), expected_args=[ ('https://chromedriver.storage.googleapis.com' '/LATEST_RELEASE_1.2.3', ), ])) self.exit_stack.enter_context( self.swap_with_checks(common, 'wait_for_port_to_be_in_use', lambda _: None, expected_args=[(4444, )])) self.exit_stack.enter_context(servers.managed_webdriver_server()) self.exit_stack.close() self.assertEqual(len(popen_calls), 1) self.assertEqual( popen_calls[0].program_args, '%s %s start --versions.chrome 1.2.3 --quiet --standalone' % (common.NODE_BIN_PATH, common.WEBDRIVER_MANAGER_BIN_PATH))
def test_managed_webdriver_fails_to_get_chrome_version(self): popen_calls = self.exit_stack.enter_context(self.swap_popen()) self.exit_stack.enter_context(self.swap(common, 'OS_NAME', 'Linux')) self.exit_stack.enter_context(self.swap_to_always_raise( subprocess, 'check_output', error=OSError)) self.exit_stack.enter_context(self.swap_with_checks( common, 'wait_for_port_to_be_in_use', lambda _: None, called=False)) expected_regexp = 'Failed to execute "google-chrome --version" command' with self.assertRaisesRegexp(Exception, expected_regexp): self.exit_stack.enter_context(servers.managed_webdriver_server()) self.assertEqual(len(popen_calls), 0)
def test_managed_webdriver_on_window_os(self): popen_calls = self.exit_stack.enter_context(self.swap_popen()) self.exit_stack.enter_context(self.swap(common, 'OS_NAME', 'Windows')) self.exit_stack.enter_context( self.swap_to_always_return(subprocess, 'check_call')) self.exit_stack.enter_context( self.swap_to_always_return(subprocess, 'check_output', value=b'1.2.3.45')) self.exit_stack.enter_context( self.swap_to_always_return(utils, 'url_open', value=mock.Mock(read=lambda: b'1.2.3'))) self.exit_stack.enter_context( self.swap_to_always_return(common, 'is_x64_architecture', value=True)) self.exit_stack.enter_context( self.swap_with_checks( common, 'inplace_replace_file_context', lambda *_: contextlib.nullcontext(), expected_args=[ ( common.CHROME_PROVIDER_FILE_PATH, re.escape('this.osArch = os.arch();'), 'this.osArch = "x64";', ), ( common.GECKO_PROVIDER_FILE_PATH, re.escape('this.osArch = os.arch();'), 'this.osArch = "x64";', ), ])) self.exit_stack.enter_context( self.swap_with_checks(common, 'wait_for_port_to_be_in_use', lambda _: None, expected_args=[(4444, )])) self.exit_stack.enter_context(servers.managed_webdriver_server()) self.exit_stack.close() self.assertEqual(len(popen_calls), 1) self.assertEqual( popen_calls[0].program_args, '%s %s start --versions.chrome 1.2.3 --quiet --standalone' % (common.NODE_BIN_PATH, common.WEBDRIVER_MANAGER_BIN_PATH))
def run_tests(args): """Run the scripts to start end-to-end tests.""" if is_oppia_server_already_running(): sys.exit(1) install_third_party_libraries(args.skip_install) with contextlib.ExitStack() as stack: dev_mode = not args.prod_env if args.skip_build: build.modify_constants(prod_env=args.prod_env) else: build_js_files(dev_mode, source_maps=args.source_maps) stack.callback(build.set_constants_to_default) stack.enter_context(servers.managed_redis_server()) stack.enter_context(servers.managed_elasticsearch_dev_server()) if constants.EMULATOR_MODE: stack.enter_context(servers.managed_firebase_auth_emulator()) stack.enter_context( servers.managed_cloud_datastore_emulator(clear_datastore=True)) app_yaml_path = 'app.yaml' if args.prod_env else 'app_dev.yaml' stack.enter_context( servers.managed_dev_appserver( app_yaml_path, port=GOOGLE_APP_ENGINE_PORT, log_level=args.server_log_level, # Automatic restart can be disabled since we don't expect code # changes to happen while the e2e tests are running. automatic_restart=False, skip_sdk_update_check=True, env={ **os.environ, 'PORTSERVER_ADDRESS': common.PORTSERVER_SOCKET_FILEPATH, })) stack.enter_context( servers.managed_webdriver_server( chrome_version=args.chrome_driver_version)) proc = stack.enter_context( servers.managed_protractor_server( suite_name=args.suite, dev_mode=dev_mode, debug_mode=args.debug_mode, sharding_instances=args.sharding_instances, stdout=subprocess.PIPE)) print('Servers have come up.\n' 'Note: If ADD_SCREENSHOT_REPORTER is set to true in ' 'core/tests/protractor.conf.js, you can view screenshots of the ' 'failed tests in ../protractor-screenshots/') output_lines = [] while True: # Keep reading lines until an empty string is returned. Empty # strings signal that the process has ended. for line in iter(proc.stdout.readline, b''): if isinstance(line, str): # Although our unit tests always provide unicode strings, # the actual server needs this failsafe since it can output # non-unicode strings. line = line.encode('utf-8') # pragma: no cover output_lines.append(line.rstrip()) # Replaces non-ASCII characters with '?'. common.write_stdout_safe(line.decode('ascii', errors='replace')) # The poll() method returns None while the process is running, # otherwise it returns the return code of the process (an int). if proc.poll() is not None: break return output_lines, proc.returncode