class Test(TestCase): def wait(self): self.screen.waitgrab() def setUp(self): self.screen = SmartDisplay() self.screen.start() def tearDown(self): self.p.stop() self.screen.stop() # def test_empty(self): # self.p = EasyProcess('zenity --warning').start() # wnd is not ready # time.sleep(0.2) # self.assertRaises(EmptyScreenException, active_rectangles) def test_zenity(self): self.p = EasyProcess('zenity --warning').start() self.wait() ls = active_rectangles() self.assertEquals(len(ls), 1) def test_notab(self): self.p = EasyProcess('xmessage -buttons x,y,z hi').start() self.wait() ls = active_rectangles(grid=10) self.assertEquals(len(ls), 3) def test_gmessage(self): self.p = EasyProcess('gmessage -buttons x,y,z hi').start() self.wait() ls = active_rectangles() self.assertEquals(len(ls), 3)
class Test(TestCase): def wait(self): self.screen.waitgrab() def setUp(self): self.screen = SmartDisplay() self.screen.start() self.p = None def tearDown(self): self.p.stop() self.screen.stop() # def test_empty(self): # self.p = EasyProcess('zenity --warning').start() # wnd is not ready # self.assertRaises(EmptyScreenException, tab_rectangles) # def test_zenity(self): # self.p = EasyProcess('zenity --warning').start() # self.wait() # ls = tab_rectangles() # self.assertEquals(len(ls), 2) def test_notab(self): self.p = EasyProcess('xmessage hi').start() self.wait() ls = tab_rectangles() self.assertEquals(len(ls), 0) def test_gmessage(self): self.p = EasyProcess('gmessage -buttons x,y,z hi').start() self.wait() ls = tab_rectangles() self.assertEquals(len(ls), 4)
class VirtualDisplay(Service, Singletone): """ Selenium executor :type virtual_display: Display """ SHARED_VIRTUAL_DISPLAY = {} def __init__(self): super(VirtualDisplay, self).__init__() self.virtual_display = None def get_virtual_display(self): return self.virtual_display def set_virtual_display(self): if is_windows(): self.log.warning( "Cannot have virtual display on Windows, ignoring") else: if self.engine in VirtualDisplay.SHARED_VIRTUAL_DISPLAY: self.virtual_display = VirtualDisplay.SHARED_VIRTUAL_DISPLAY[ self.engine] else: width = self.parameters.get("width", 1024) height = self.parameters.get("height", 768) self.virtual_display = Display(size=(width, height)) msg = "Starting virtual display[%s]: %s" self.log.info(msg, self.virtual_display.size, self.virtual_display.new_display_var) self.virtual_display.start() VirtualDisplay.SHARED_VIRTUAL_DISPLAY[ self.engine] = self.virtual_display def free_virtual_display(self): if self.virtual_display and self.virtual_display.is_alive(): self.virtual_display.stop() if self.engine in VirtualDisplay.SHARED_VIRTUAL_DISPLAY: del VirtualDisplay.SHARED_VIRTUAL_DISPLAY[self.engine] def startup(self): self.set_virtual_display() def check_virtual_display(self): if self.virtual_display: if not self.virtual_display.is_alive(): self.log.info("Virtual display out: %s", self.virtual_display.stdout) self.log.warning("Virtual display err: %s", self.virtual_display.stderr) raise TaurusInternalException("Virtual display failed: %s" % self.virtual_display.return_code) def check(self): self.check_virtual_display() return False def shutdown(self): self.free_virtual_display()
def test_slowshot(self): disp = SmartDisplay(visible=0).start() py = path(__file__).parent / ('slowgui.py') proc = EasyProcess('python ' + py).start() img = disp.waitgrab() proc.stop() disp.stop() eq_(img is not None, True)
def test_slowshot(): disp = SmartDisplay(visible=False).start() py = Path(__file__).parent / ("slowgui.py") proc = EasyProcess([python, py]).start() img = disp.waitgrab() proc.stop() disp.stop() assert img is not None
def cli_parse(): '''Parse command-line arguments''' options = {'title': None, 'desc': None, 'date': None, 'time': None, 'id': None} parser = argparse.ArgumentParser() parser.add_argument("action", help='''use "create" to create a new event\n "update" to update an event\n"details" to get event info''') # noqa parser.add_argument("--title", help="event title") parser.add_argument("--date", help="event date") parser.add_argument("--id", help="event id") parser.add_argument("--desc", help="event description") parser.add_argument("--filedesc", help="path to txt file w/ event description", # noqa type=argparse.FileType('r')) parser.add_argument("--otp", help="2-step verification code") parser.add_argument("--show", help="1 to display the browser, 0 for invisible virtual display", # noqa default=0, type=int) try: args = parser.parse_args() except: parser.print_help() exit(1) disp = None if not args.show: # set up invisible virtual display from pyvirtualdisplay.smartdisplay import SmartDisplay try: disp = SmartDisplay(visible=0, bgcolor='black').start() atexit.register(disp.stop) except: if disp: disp.stop() raise if args.title: options['title'] = args.title if args.desc: options['desc'] = args.desc elif args.filedesc: options['desc'] = args.filedesc.read() if args.date: options['date'] = dtparser.parse(args.date).strftime('%Y-%m-%d') options['time'] = dtparser.parse(args.date).strftime('%I:%M %p') if args.id: options['id'] = args.id if args.otp: options['otp'] = args.otp options['action'] = args.action return options
def test_disp(self): vd = SmartDisplay().start() d = SmartDisplay(visible=1).start().sleep(2).stop() self.assertEquals(d.return_code, 0) d = SmartDisplay(visible=0).start().stop() self.assertEquals(d.return_code, 0) vd.stop()
class VirtualDisplay(Service, Singletone): """ Selenium executor :type virtual_display: Display """ SHARED_VIRTUAL_DISPLAY = None def __init__(self): super(VirtualDisplay, self).__init__() self.virtual_display = None def get_virtual_display(self): return self.virtual_display def set_virtual_display(self): if is_windows(): self.log.warning("Cannot have virtual display on Windows, ignoring") return if VirtualDisplay.SHARED_VIRTUAL_DISPLAY: self.virtual_display = VirtualDisplay.SHARED_VIRTUAL_DISPLAY else: width = self.parameters.get("width", 1024) height = self.parameters.get("height", 768) self.virtual_display = Display(size=(width, height)) msg = "Starting virtual display[%s]: %s" self.log.info(msg, self.virtual_display.size, self.virtual_display.new_display_var) self.virtual_display.start() VirtualDisplay.SHARED_VIRTUAL_DISPLAY = self.virtual_display self.engine.shared_env.set({'DISPLAY': os.environ['DISPLAY']}) # backward compatibility def free_virtual_display(self): if self.virtual_display and self.virtual_display.is_alive(): self.virtual_display.stop() if VirtualDisplay.SHARED_VIRTUAL_DISPLAY: VirtualDisplay.SHARED_VIRTUAL_DISPLAY = None def startup(self): self.set_virtual_display() def check_virtual_display(self): if self.virtual_display: if not self.virtual_display.is_alive(): self.log.info("Virtual display out: %s", self.virtual_display.stdout) self.log.warning("Virtual display err: %s", self.virtual_display.stderr) raise TaurusInternalException("Virtual display failed: %s" % self.virtual_display.return_code) def check(self): self.check_virtual_display() return False def shutdown(self): self.free_virtual_display()
class CuiJsTestCase(LiveServerTestCase): def setUp(self): # See https://code.djangoproject.com/ticket/10827 from django.contrib.contenttypes.models import ContentType ContentType.objects.clear_cache() if not os.environ.get('SHOW_SELENIUM'): self.display = SmartDisplay(visible=0, size=(1024, 768)) self.display.start() remote_selenium = os.environ.get('REMOTE_SELENIUM') if not remote_selenium: self.driver = webdriver.Firefox() else: self.driver = webdriver.Remote( command_executor=remote_selenium, desired_capabilities={ 'browserName': 'unknown', 'javascriptEnabled': True, 'platform': 'ANY', 'version': '' } ) def tearDown(self): if hasattr(self, 'driver'): self.driver.quit() if hasattr(self, 'display'): self.display.stop() def wait_until_expr(self, expr, timeout=60): WebDriverWait(self.driver, timeout).until( lambda driver: driver.execute_script('return (%s)' % expr)) def test(self): sys.stderr.write('\n\nRunning candidate UI unit tests...\n') sys.stderr.flush() tests_url = self.live_server_url + reverse('cui_test') jasmine_spec = os.environ.get('JASMINE_SPEC') if jasmine_spec: tests_url += "?spec={}".format(urlquote(jasmine_spec)) self.driver.get(tests_url) self.wait_until_expr('window.seleniumReporter') runner = SeleniumRunner(self.driver, sys.stderr) success = runner.run() self.assertTrue(success, 'JS tests failed. See full report on stderr')
class CuiJsTestCase(StaticLiveServerTestCase): def setUp(self): # See https://code.djangoproject.com/ticket/10827 from django.contrib.contenttypes.models import ContentType ContentType.objects.clear_cache() if not os.environ.get('SHOW_SELENIUM'): self.display = SmartDisplay(visible=0, size=(1024, 768)) self.display.start() remote_selenium = os.environ.get('REMOTE_SELENIUM') if not remote_selenium: self.driver = webdriver.Firefox() else: self.driver = webdriver.Remote(command_executor=remote_selenium, desired_capabilities={ 'browserName': 'unknown', 'javascriptEnabled': True, 'platform': 'ANY', 'version': '' }) def tearDown(self): if hasattr(self, 'driver'): self.driver.quit() if hasattr(self, 'display'): self.display.stop() def wait_until_expr(self, expr, timeout=60): WebDriverWait(self.driver, timeout).until( lambda driver: driver.execute_script('return (%s)' % expr)) def test(self): sys.stderr.write('\n\nRunning candidate UI unit tests...\n') sys.stderr.flush() tests_url = self.live_server_url + reverse('cui_test') jasmine_spec = os.environ.get('JASMINE_SPEC') if jasmine_spec: tests_url += "?spec={}".format(urlquote(jasmine_spec)) self.driver.get(tests_url) self.wait_until_expr('window.seleniumReporter') runner = SeleniumRunner(self.driver, sys.stderr) success = runner.run() self.assertTrue(success, 'JS tests failed. See full report on stderr')
def startViewer(index, watchURL): user_data_dir = args.chrome_data_dir_default + "_tmp" + str(index) rtt_file = os.path.join(args.log_base, "rtt_%d" % index) snapshot_file = os.path.join(args.log_base, "snapshot_%d" % index) debug_port = 9222 + index # Open a chrome window attached to a debugging port. os.system('rm -r %s; cp -r %s %s' % (user_data_dir, args.chrome_data_dir_default, user_data_dir)) cmd = ' '.join([ '%s' % args.chrome_bin, '--remote-debugging-port=%d' % debug_port, '--user-data-dir=%s' % user_data_dir, '--enable-devtools-experiments' ]) disp = SmartDisplay(visible=0, bgcolor='black') disp.start() chrome = subprocess.Popen('%s %s' % (cmd, watchURL), shell=True) print 'Launched chrome with: %s' % cmd options = Options() options.add_experimental_option("debuggerAddress", '127.0.0.1:%d' % debug_port) driver = webdriver.Chrome(chromedriver_bin, chrome_options=options) print '%d Launched chromedriver' % index print '%d Loaded %s' % (index, watchURL) time.sleep(5) # Click the video to begin playing. js = "document.getElementsByTagName('video')[0].click(); document.querySelector('button[data-testid=fullscreen_control]').click()" driver.execute_script(js) # Only one client can be attached to the remote debugging port at a time. driver.quit() # Remove the driver and start a viewer to record the downloaded video. print '%d Quit chrome driver' % index time.sleep(2) viewer = subprocess.Popen("node record_latency.js %d %d %s %s" % (debug_port, 20, rtt_file, snapshot_file), shell=True) screenshot_dir = '%s/screenshots' % args.log_base if not os.path.exists(screenshot_dir): os.makedirs(screenshot_dir) count = 0 while True: im = disp.grab() count = count + 1 #print 'c-%d' % count im.save('%s/%d_%d.jpg' % (screenshot_dir, long(time.time() * 1000), count)) disp.stop() return [chrome, viewer]
class Test(TestCase): def wait(self): self.screen.waitgrab() def setUp(self): self.screen = SmartDisplay(visible=VISIBLE) self.screen.start() self.p = None def tearDown(self): self.p.stop() self.screen.stop() def test_zenity(self): self.p = EasyProcess('zenity --warning').start() self.wait() send_key('\n') self.assertFalse(getbbox(grab())) self.p = EasyProcess('zenity --warning').start() self.wait() send_key_list(['\n']) self.assertFalse(getbbox(grab())) self.p = EasyProcess('zenity --warning').start() self.wait() send_key(' ') self.assertFalse(getbbox(grab())) self.p = EasyProcess('zenity --warning').start() self.wait() send_key('x') self.assertTrue(getbbox(grab())) def test_gcalctool1(self): self.p = EasyProcess('gnome-calculator').start() self.wait() focus_wnd() send_key('ctrl+q') time.sleep(1) # img_debug(grab(), 'ctrl+q') self.assertFalse(getbbox(grab()))
class RealBrowser(webdriver.Firefox): def __init__(self, timeout=30): self._abstract_display = SmartDisplay(visible=0) self._abstract_display.start() super(RealBrowser, self).__init__() self.implicitly_wait(timeout) def quit(self): super(RealBrowser, self).quit() self._abstract_display.stop() @timeout(REQUEST_TIMEOUT) def _open(self, url): self.get(url) def open(self, url): try: self._open(url) return True except Exception, e: logger.error('network error for %s: %s', url, str(e))
class CuiJsTestCase(LiveServerTestCase): def setUp(self): if not os.environ.get('SHOW_SELENIUM'): self.display = SmartDisplay(visible=0, size=(1024, 768)) self.display.start() self.driver = webdriver.Firefox() def tearDown(self): if hasattr(self, 'driver'): self.driver.quit() if hasattr(self, 'display'): self.display.stop() def wait_until_expr(self, expr, timeout=60): WebDriverWait(self.driver, timeout).until( lambda driver: driver.execute_script('return (%s)' % expr)) def test(self): sys.stderr.write('\n\nRunning candidate UI unit tests...\n') sys.stderr.flush() self.driver.get(self.live_server_url+reverse('cui_test')) self.wait_until_expr('window.jsApiReporter !== undefined && window.jsApiReporter.finished') specs = self.driver.execute_script('return window.jsApiReporter.specs()') self.assertTrue(len(specs) > 0, 'No test results found! The tests probably contain syntax errors.') passed = True for spec in specs: sys.stderr.write(' %s ... %s\n' % (spec['fullName'], spec['status'])) if spec['status'] != 'passed': passed = False for exp in spec['failedExpectations']: sys.stderr.write(' %s\n' % exp['message']) sys.stderr.write('Access full report at %s\n\n' % reverse('cui_test')) sys.stderr.flush() self.assertTrue(passed, 'JS tests failed. See full report on stderr')
class SeleniumExecutor(AbstractSeleniumExecutor, WidgetProvider, FileLister): """ Selenium executor :type virtual_display: Display :type runner: SubprocessedExecutor """ SUPPORTED_RUNNERS = ["nose", "junit", "testng", "rspec", "mocha"] def __init__(self): super(SeleniumExecutor, self).__init__() self.additional_env = {} self.virtual_display = None self.end_time = None self.runner = None self.report_file = None self.scenario = None self.script = None self.generated_methods = BetterDict() self.runner_working_dir = None self.register_reader = True def get_virtual_display(self): return self.virtual_display def add_env(self, env): self.additional_env.update(env) def set_virtual_display(self): display_conf = self.settings.get("virtual-display") if display_conf: if is_windows(): self.log.warning("Cannot have virtual display on Windows, ignoring") else: if self.engine in SeleniumExecutor.SHARED_VIRTUAL_DISPLAY: self.virtual_display = SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[self.engine] else: width = display_conf.get("width", 1024) height = display_conf.get("height", 768) self.virtual_display = Display(size=(width, height)) msg = "Starting virtual display[%s]: %s" self.log.info(msg, self.virtual_display.size, self.virtual_display.new_display_var) self.virtual_display.start() SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[self.engine] = self.virtual_display def free_virtual_display(self): if self.virtual_display and self.virtual_display.is_alive(): self.virtual_display.stop() if self.engine in SeleniumExecutor.SHARED_VIRTUAL_DISPLAY: del SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[self.engine] def get_runner_working_dir(self): if self.runner_working_dir is None: self.runner_working_dir = self.engine.create_artifact("classes", "") return self.runner_working_dir def _get_testng_xml(self): if 'testng-xml' in self.scenario: testng_xml = self.scenario.get('testng-xml') if testng_xml: return testng_xml else: return None # empty value for switch off testng.xml path autodetect script_path = self.get_script_path() if script_path: script_dir = get_full_path(script_path, step_up=1) testng_xml = os.path.join(script_dir, 'testng.xml') if os.path.exists(testng_xml): self.log.info("Detected testng.xml file at %s", testng_xml) self.scenario['testng-xml'] = testng_xml return testng_xml return None def _create_runner(self, report_file): script_type = self.detect_script_type() runner = self.engine.instantiate_module(script_type) runner.parameters = self.parameters runner.provisioning = self.provisioning runner.execution = self.execution runner.execution['executor'] = script_type if script_type == "nose": runner.generated_methods = self.generated_methods runner.execution["test-mode"] = "selenium" elif script_type == "junit": pass elif script_type == "testng": testng_config = self._get_testng_xml() if testng_config: runner.execution['testng-xml'] = self.engine.find_file(testng_config) elif script_type == "rspec": pass elif script_type == "mocha": pass else: raise TaurusConfigError("Unsupported script type: %s" % script_type) runner.execution["report-file"] = report_file # TODO: shouldn't it be the field? return runner def _register_reader(self, report_file): if self.engine.is_functional_mode(): reader = FuncSamplesReader(report_file, self.engine, self.log, self.generated_methods) if isinstance(self.engine.aggregator, FunctionalAggregator): self.engine.aggregator.add_underling(reader) else: reader = LoadSamplesReader(report_file, self.log, self.generated_methods) if isinstance(self.engine.aggregator, ConsolidatingAggregator): self.engine.aggregator.add_underling(reader) return reader def prepare(self): if self.get_load().concurrency and self.get_load().concurrency > 1: msg = 'Selenium supports concurrency in cloud provisioning mode only\n' msg += 'For details look at http://gettaurus.org/docs/Cloud.md' self.log.warning(msg) self.set_virtual_display() self.scenario = self.get_scenario() self.script = self.get_script_path() self.report_file = self.engine.create_artifact("selenium_tests_report", ".ldjson") self.runner = self._create_runner(self.report_file) self.runner.prepare() if isinstance(self.runner, NoseTester): self.script = self.runner._script if self.register_reader: self.reader = self._register_reader(self.report_file) def detect_script_type(self): if not self.script and "requests" in self.scenario: return "nose" if not os.path.exists(self.script): raise TaurusConfigError("Script '%s' doesn't exist" % self.script) if "runner" in self.execution: runner = self.execution["runner"] if runner not in SeleniumExecutor.SUPPORTED_RUNNERS: msg = "Runner '%s' is not supported. Supported runners: %s" raise TaurusConfigError(msg % (runner, SeleniumExecutor.SUPPORTED_RUNNERS)) self.log.debug("Using script type: %s", runner) return runner file_types = set() if os.path.isfile(self.script): # regular file received file_types.add(os.path.splitext(self.script)[1].lower()) else: # dir received: check contained files for file_name in get_files_recursive(self.script): file_types.add(os.path.splitext(file_name)[1].lower()) if '.java' in file_types or '.jar' in file_types: if self._get_testng_xml() is not None: script_type = 'testng' else: script_type = 'junit' elif '.py' in file_types: script_type = 'nose' elif '.rb' in file_types: script_type = 'rspec' elif '.js' in file_types: script_type = 'mocha' else: raise TaurusConfigError("Unsupported script type: %s" % self.script) self.log.debug("Detected script type: %s", script_type) return script_type def startup(self): """ Start runner :return: """ self.start_time = time.time() self.runner.env = self.additional_env self.runner.startup() def check_virtual_display(self): if self.virtual_display: if not self.virtual_display.is_alive(): self.log.info("Virtual display out: %s", self.virtual_display.stdout) self.log.warning("Virtual display err: %s", self.virtual_display.stderr) raise TaurusInternalException("Virtual display failed: %s" % self.virtual_display.return_code) def check(self): """ check if test completed :return: """ if self.widget: self.widget.update() self.check_virtual_display() return self.runner.check() def report_test_duration(self): if self.start_time: self.end_time = time.time() self.log.debug("Selenium tests ran for %s seconds", self.end_time - self.start_time) def shutdown(self): """ shutdown test_runner :return: """ self.runner.shutdown() self.report_test_duration() def post_process(self): if os.path.exists("geckodriver.log"): self.engine.existing_artifact("geckodriver.log", True) self.free_virtual_display() def has_results(self): if self.reader and self.reader.read_records: return True else: return False def get_widget(self): if not self.widget: self.widget = SeleniumWidget(self.script, self.runner._stdout_file) return self.widget def resource_files(self): resources = [] self.scenario = self.get_scenario() script = self.scenario.get(Scenario.SCRIPT, None) if script: resources.append(script) resources.extend(self.scenario.get("additional-classpath", [])) resources.extend(self.settings.get("additional-classpath", [])) testng_config = self._get_testng_xml() if testng_config: resources.append(testng_config) return resources
class Hangouts(object): """ Main class for controlling hangout calls. Initialization does two things: 1. Makes sure that there is active X session. 2. Starts the browser. If 'DISPLAY' can't be found in os.environ than new X session starts. Starting new session handels `PyVirtualDisplay`_. .. _PyVirtualDisplay: http://ponty.github.io/PyVirtualDisplay/ For handling browser used seleniumwrapper library. .. testsetup:: HangoutsBase import os os.environ['DISPLAY'] = '1' from hangout_api import Hangouts from hangout_api.tests.doctests_utils import DummySelenium import seleniumwrapper def get_attribute(self, name): if name == 'aria-label': return ' John Doe ' elif name == 'data-userid': return '108775712935' else: return 'hello' DummySelenium.get_attribute = get_attribute seleniumwrapper.create = DummySelenium .. testsetup:: HangoutsBase2 import os os.environ['DISPLAY'] = '1' from hangout_api import Hangouts from hangout_api.tests.doctests_utils import DummySelenium import seleniumwrapper DummySelenium.location = {'x': 1} seleniumwrapper.create = DummySelenium hangout = Hangouts() .. doctest:: HangoutsBase >>> hangout = Hangouts() """ def __init__(self, executable_path=None, chrome_options=None): self.hangout_id = None self.on_air = None # lets start display in case if no is available self.display = None if not os.environ.get('DISPLAY'): self.display = SmartDisplay() self.display.start() kwargs = {'executable_path': executable_path or CHROMEDRV_PATH} if chrome_options is not None: kwargs['chrome_options'] = chrome_options self.browser = selwrap.create('chrome', **kwargs) self.utils = Utils(self.browser) for name, instance in getUtilitiesFor(IModule): setattr(self, name, instance(self.utils)) def start(self, on_air=None): """ Start a new hangout. After new hangout is created its id is stored in 'hangout_id' attribure .. doctest:: HangoutsBase >>> hangout.start() >>> hangout.hangout_id 'gs4pp6g62w65moctfqsvihzq2qa' To start OnAir just pass on_air argument to 'start' method. .. doctest:: HangoutsBase >>> hangout.start( ... on_air={'name':'My OnAir', 'attendees':['Friends']}) >>> hangout.start(on_air='https://plus.google.com/events/df34...') """ # onair if on_air is not None: self.on_air = on_air if isinstance(on_air, dict): # in case if on_air is a dict create new hangout event _create_hangout_event( self.browser, on_air['name'], on_air['attendees']) else: # otherwise (hangout is a string) go to event page self.browser.get(on_air) # on event page, redirecting can take some time self.browser.xpath( '//div[@data-tooltip="Start the Hangout On Air"]', timeout=TIMEOUTS.extralong).click(TIMEOUTS.fast) for name, instance in getUtilitiesFor(IOnAirModule): setattr(self, name, instance(self.utils)) else: if not self.browser.current_url.startswith( URLS.hangouts_active_list): self.browser.get(URLS.hangouts_active_list) # G+ opens new window for new hangout, so we need to # switch selenium to it self.browser.by_text( 'Start a video Hangout').click(timeout=TIMEOUTS.fast) # waiting until new window appears tries_n_time_until_true( lambda: len(self.browser.window_handles) <= 1, try_num=100) # self.browser.close() # closing old window self.browser.switch_to_window(self.browser.window_handles[-1]) self.utils.click_cancel_button_if_there_is_one( timeout=TIMEOUTS.extralong) if self.on_air: # waiting for broadcasting to be ready broadcast_button = self.browser.by_text( 'Start broadcast', timeout=TIMEOUTS.long) tries_n_time_until_true(broadcast_button.is_displayed, try_num=600) # setting hangout id property self.hangout_id = self.browser.current_url.replace( URLS.hangout_session_base, '', 1).split('?', 1)[0] # @retry(stop_max_attempt_number=3) def connect(self, hangout_id): """ Connect to an existing hangout. Takes id of targeted hangout as argument. Also it sets hangout_id property: .. doctest:: HangoutsBase >>> hangout.connect('fnar4989hf9834h') >>> hangout.hangout_id 'fnar4989hf9834h' """ self.hangout_id = hangout_id self.browser.get(URLS.hangout_session_base + hangout_id) # there may be a big delay before 'Join' button appears, so there is a # need wait longer than usual join_button = self.browser.xpath( '//*[text()="Join" or text()="Okay, got it!"]', timeout=TIMEOUTS.long) button_text = names_cleaner(join_button.get_attribute('innerText')) if button_text == 'Okay, got it!': # to join hangout we need to set agreement checkbox self.browser.xpath('//*[@role="presentation"]').click( timeout=TIMEOUTS.fast) join_button.click(timeout=TIMEOUTS.average) self.browser.by_text('Join', timeout=TIMEOUTS.long).click( timeout=TIMEOUTS.fast) @retry(stop_max_attempt_number=3) def login(self, username, password, otp=None): """ Log in to google plus. *otp* argument is one time password and it's optional, set it only if you're using 2-factor authorization. .. doctest:: HangoutsBase >>> hangout.login('*****@*****.**', 'password') >>> hangout.login('*****@*****.**', 'password', otp='123456') """ # Open login form and sing in with credentials self.browser.get(URLS.service_login) self.browser.by_id('Email').send_keys(username) self.browser.by_id('Passwd').send_keys(password) self.browser.by_id('signIn').click(timeout=TIMEOUTS.fast) # filling up one time password if provides if otp: self.browser.by_id('smsUserPin').send_keys(otp) self.browser.by_id('smsVerifyPin').click(timeout=TIMEOUTS.fast) # checking if log in was successful if not self.utils.is_logged_in: raise LoginError( 'Wasn\'t able to login. Check if credentials are correct' 'and make sure that you have G+ account activated') @retry(stop_max_attempt_number=3) def invite(self, participants): """ Invite person or circle to hangout: .. doctest:: HangoutsBase2 >>> hangout.invite("*****@*****.**") >>> hangout.invite(["*****@*****.**", "Public", "Friends"]) """ self.utils.click_cancel_button_if_there_is_one() if not any(isinstance(participants, i) for i in (list, tuple)): participants = [participants, ] # click on Invite People button self.utils.click_menu_element('//div[@aria-label="Invite People"]') input_field = self.browser.xpath( '//input[@placeholder="+ Add names, circles, or email addresses"]') input_field.click() input_field.clear() for participant in participants: input_field.send_keys(participant) sleep(1) # need to wait a bit for HG to make request input_field.send_keys(Keys.RETURN) self.browser.by_text('Invite').click(timeout=TIMEOUTS.fast) # making sure that invitation is posted xpath = '//*[text()="Invitation posted"'\ 'or text()="Waiting for people to join this video call..."]' self.browser.xpath(xpath) @retry(stop_max_attempt_number=3) def participants(self): """ Returns list of namedtuples of current participants: .. doctest:: HangoutsBase >>> hangout.participants() [Participant(name='John Doe', profile_id='108775712935')] """ xpath = '//div[@data-userid]' # for some reason some persons can be listed twice, so let's # filter them with dict participants = { p.get_attribute('data-userid'): p.get_attribute( 'aria-label')[5:-11] for p in self.browser.xpath(xpath, eager=True)} return [Participant(name=pname, profile_id=pid) for pid, pname in participants.items()] @retry(stop_max_attempt_number=3) def disconnect(self): """ Leave hangout (equal on clicking on "Leave call" button). After leaving the call you can create a new one or connect to existing. .. doctest:: HangoutsBase2 >>> hangout.disconnect() """ self.utils.click_cancel_button_if_there_is_one() self.utils.click_menu_element('//div[@aria-label="Leave call"]') self.hangout_id = None if self.on_air is not None: # removing properties that is available only for OnAir for name, _ in getUtilitiesFor(IOnAirModule): delattr(self, name) self.on_air = None # waiting until hangout windows closes tries_n_time_until_true( lambda: len(self.browser.window_handles) == 1, try_num=100) self.browser.switch_to_window(self.browser.window_handles[-1]) def __del__(self): # and quiting browser and display if self.browser: try: if self.hangout_id and self.browser.window_handles: # leaving the call first self.disconnect() finally: self.browser.quit() if self.display is not None: self.display.stop()
class SeleniumExecutor(AbstractSeleniumExecutor, WidgetProvider, FileLister): """ Selenium executor :type virtual_display: Display :type runner: SubprocessedExecutor """ SUPPORTED_RUNNERS = ["nose", "junit", "testng", "rspec", "mocha"] def __init__(self): super(SeleniumExecutor, self).__init__() self.additional_env = {} self.virtual_display = None self.end_time = None self.runner = None self.script = None self.generated_methods = BetterDict() self.runner_working_dir = None def get_virtual_display(self): return self.virtual_display def add_env(self, env): self.additional_env.update(env) def set_virtual_display(self): display_conf = self.settings.get("virtual-display") if display_conf: if is_windows(): self.log.warning( "Cannot have virtual display on Windows, ignoring") else: if self.engine in SeleniumExecutor.SHARED_VIRTUAL_DISPLAY: self.virtual_display = SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[ self.engine] else: width = display_conf.get("width", 1024) height = display_conf.get("height", 768) self.virtual_display = Display(size=(width, height)) msg = "Starting virtual display[%s]: %s" self.log.info(msg, self.virtual_display.size, self.virtual_display.new_display_var) self.virtual_display.start() SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[ self.engine] = self.virtual_display def free_virtual_display(self): if self.virtual_display and self.virtual_display.is_alive(): self.virtual_display.stop() if self.engine in SeleniumExecutor.SHARED_VIRTUAL_DISPLAY: del SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[self.engine] def get_runner_working_dir(self): if self.runner_working_dir is None: self.runner_working_dir = self.engine.create_artifact( "classes", "") return self.runner_working_dir def create_runner(self): runner_type = self.get_runner_type() self.runner = self.engine.instantiate_module(runner_type) # todo: deprecated, remove it later self.runner.settings.merge( self.settings.get('selenium-tools').get(runner_type)) self.runner.parameters = self.parameters self.runner.provisioning = self.provisioning self.runner.execution = self.execution self.runner.execution['executor'] = runner_type if runner_type == "nose": self.runner.execution["test-mode"] = "selenium" def prepare(self): if self.get_load().concurrency and self.get_load().concurrency > 1: msg = 'Selenium supports concurrency in cloud provisioning mode only\n' msg += 'For details look at http://gettaurus.org/docs/Cloud.md' self.log.warning(msg) self.set_virtual_display() self.create_runner() self.runner.prepare() self.script = self.runner.script def get_runner_type(self): if "runner" in self.execution: runner = self.execution["runner"] if runner not in SeleniumExecutor.SUPPORTED_RUNNERS: msg = "Runner '%s' is not supported. Supported runners: %s" raise TaurusConfigError( msg % (runner, SeleniumExecutor.SUPPORTED_RUNNERS)) self.log.debug("Using script type: %s", runner) return runner script_name = self.get_script_path() if script_name: return self.detect_script_type(script_name) else: if "requests" in self.get_scenario(): return "nose" else: raise TaurusConfigError( "You must specify either script or list of requests to run Selenium" ) def resource_files(self): self.create_runner() return self.runner.resource_files() def detect_script_type(self, script_name): if not os.path.exists(script_name): raise TaurusConfigError("Script '%s' doesn't exist" % script_name) file_types = set() # gather file extensions and choose script_type according to priority if os.path.isfile(script_name): # regular file received file_types.add(os.path.splitext(script_name)[1].lower()) else: # dir received: check contained files for file_name in get_files_recursive(script_name): file_types.add(os.path.splitext(file_name)[1].lower()) if '.java' in file_types or '.jar' in file_types: # todo: next detection logic is duplicated in TestNGTester - can we avoid it? script_dir = get_full_path(self.get_script_path(), step_up=1) if os.path.exists(os.path.join( script_dir, 'testng.xml')) or self.execution.get( 'testng-xml', None): script_type = 'testng' else: script_type = 'junit' elif '.py' in file_types: script_type = 'nose' elif '.rb' in file_types: script_type = 'rspec' elif '.js' in file_types: script_type = 'mocha' else: raise TaurusConfigError( "Supported script files not found, script detection is failed") self.log.debug("Detected script type: %s", script_type) return script_type def startup(self): """ Start runner :return: """ self.start_time = time.time() self.runner.env = self.additional_env self.runner.startup() def check_virtual_display(self): if self.virtual_display: if not self.virtual_display.is_alive(): self.log.info("Virtual display out: %s", self.virtual_display.stdout) self.log.warning("Virtual display err: %s", self.virtual_display.stderr) raise TaurusInternalException("Virtual display failed: %s" % self.virtual_display.return_code) def check(self): """ check if test completed :return: """ if self.widget: self.widget.update() self.check_virtual_display() return self.runner.check() def report_test_duration(self): if self.start_time: self.end_time = time.time() self.log.debug("Selenium tests ran for %s seconds", self.end_time - self.start_time) def shutdown(self): """ shutdown test_runner :return: """ self.runner.shutdown() self.report_test_duration() def post_process(self): if os.path.exists("geckodriver.log"): self.engine.existing_artifact("geckodriver.log", True) self.free_virtual_display() def has_results(self): return self.runner.has_results() def get_widget(self): if not self.widget: self.widget = SeleniumWidget(self.script, self.runner.stdout_file) return self.widget
# ----------------------------------------------------------------------------- VIRTUAL_SIZE = (1024, 2000) # PhantomJS doesn't need a display disp = None if args.virtual and args.browser != "PhantomJS": from pyvirtualdisplay.smartdisplay import SmartDisplay try: disp = SmartDisplay(visible=0, bgcolor='black', size=VIRTUAL_SIZE).start() atexit.register(disp.stop) except: if disp: disp.stop() raise # Start up the web browser and run the tests. # ---------------------------------------------------------------------------- from selenium import webdriver from selenium.common import exceptions as selenium_exceptions from selenium.webdriver.common.keys import Keys as selenium_keys driver_arguments = {} if args.browser == "Chrome": import tempfile import shutil # We reference shutil to make sure it isn't garbaged collected before we
class SeleniumExecutor(ScenarioExecutor, WidgetProvider, FileLister): """ Selenium executor :type virtual_display: Display """ SELENIUM_DOWNLOAD_LINK = "http://selenium-release.storage.googleapis.com/{version}/" \ "selenium-server-standalone-{version}.0.jar" SELENIUM_VERSION = "2.48" JUNIT_DOWNLOAD_LINK = "http://search.maven.org/remotecontent?filepath=junit/junit/{version}/junit-{version}.jar" JUNIT_VERSION = "4.12" JUNIT_MIRRORS_SOURCE = "http://search.maven.org/solrsearch/select?q=g%3A%22junit%22%20AND%20a%3A%22junit%22%20" \ "AND%20v%3A%22{version}%22&rows=20&wt=json".format(version=JUNIT_VERSION) HAMCREST_DOWNLOAD_LINK = "https://hamcrest.googlecode.com/files/hamcrest-core-1.3.jar" SUPPORTED_TYPES = [".py", ".jar", ".java"] def __init__(self): super(SeleniumExecutor, self).__init__() self.virtual_display = None self.start_time = None self.end_time = None self.runner = None self.widget = None self.reader = None self.kpi_file = None self.err_jtl = None self.runner_working_dir = None self.scenario = None def prepare(self): display_conf = self.settings.get("virtual-display") if display_conf: if is_windows(): self.log.warning("Cannot have virtual display on Windows, ignoring") else: width = display_conf.get("width", 1024) height = display_conf.get("height", 768) self.virtual_display = Display(size=(width, height)) self.scenario = self.get_scenario() self._verify_script() self.kpi_file = self.engine.create_artifact("selenium_tests_report", ".csv") self.err_jtl = self.engine.create_artifact("selenium_tests_err", ".xml") script_type = self.detect_script_type(self.scenario.get(Scenario.SCRIPT)) if script_type == ".py": runner_class = NoseTester runner_config = self.settings.get("selenium-tools").get("nose") elif script_type == ".jar" or script_type == ".java": runner_class = JUnitTester runner_config = self.settings.get("selenium-tools").get("junit") runner_config['props-file'] = self.engine.create_artifact("customrunner", ".properties") else: raise ValueError("Unsupported script type: %s" % script_type) runner_config["script-type"] = script_type self.runner_working_dir = self.engine.create_artifact(runner_config.get("working-dir", "classes"), "") runner_config["working-dir"] = self.runner_working_dir runner_config.get("artifacts-dir", self.engine.artifacts_dir) runner_config.get("working-dir", self.runner_working_dir) runner_config.get("report-file", self.kpi_file) runner_config.get("err-file", self.err_jtl) runner_config.get("stdout", self.engine.create_artifact("junit", ".out")) runner_config.get("stderr", self.engine.create_artifact("junit", ".err")) self._cp_resource_files(self.runner_working_dir) self.runner = runner_class(runner_config, self.scenario, self.get_load(), self.log) self.runner.prepare() self.reader = JTLReader(self.kpi_file, self.log, self.err_jtl) if isinstance(self.engine.aggregator, ConsolidatingAggregator): self.engine.aggregator.add_underling(self.reader) def _verify_script(self): if not self.scenario.get("script"): if self.scenario.get("requests"): self.scenario["script"] = self.__tests_from_requests() else: raise RuntimeError("Nothing to test, no requests were provided in scenario") def _cp_resource_files(self, runner_working_dir): """ :return: """ script = self.scenario.get("script") if Scenario.SCRIPT in self.scenario: if os.path.isdir(script): shutil.copytree(script, runner_working_dir) else: os.makedirs(runner_working_dir) shutil.copy2(script, runner_working_dir) def detect_script_type(self, script_path): """ checks if script is java or python if it's folder or single script :return: """ if not isinstance(script_path, string_types) and not isinstance(script_path, text_type): raise RuntimeError("Nothing to test, no files were provided in scenario") test_files = [] for dir_entry in os.walk(script_path): if dir_entry[2]: for test_file in dir_entry[2]: if os.path.splitext(test_file)[1].lower() in SeleniumExecutor.SUPPORTED_TYPES: test_files.append(test_file) if os.path.isdir(script_path): file_ext = os.path.splitext(test_files[0])[1].lower() else: file_ext = os.path.splitext(script_path)[1] if file_ext not in SeleniumExecutor.SUPPORTED_TYPES: raise RuntimeError("Supported tests types %s was not found" % SeleniumExecutor.SUPPORTED_TYPES) return file_ext def startup(self): """ Start runner :return: """ self.start_time = time.time() if self.virtual_display: msg = "Starting virtual display[%s]: %s" self.log.info(msg, self.virtual_display.size, self.virtual_display.new_display_var) self.virtual_display.start() self.runner.run_tests() def check(self): """ check if test completed :return: """ if self.widget: self.widget.update() if self.virtual_display: if not self.virtual_display.is_alive(): self.log.info("Virtual display out: %s", self.virtual_display.stdout) self.log.warning("Virtual display err: %s", self.virtual_display.stderr) raise RuntimeError("Virtual display failed: %s" % self.virtual_display.return_code) return self.runner.is_finished() def shutdown(self): """ shutdown test_runner :return: """ try: self.runner.shutdown() finally: if self.virtual_display and self.virtual_display.is_alive(): self.virtual_display.stop() if self.start_time: self.end_time = time.time() self.log.debug("Selenium tests ran for %s seconds", self.end_time - self.start_time) def post_process(self): if self.reader and not self.reader.read_records: raise RuntimeWarning("Empty results, most likely Selenium failed") def get_widget(self): if not self.widget: self.widget = SeleniumWidget(self.scenario.get("script"), self.runner.settings.get("stdout")) return self.widget def resource_files(self): if not self.scenario: self.scenario = self.get_scenario() if "script" not in self.scenario: return [] script = self.scenario.get("script") script_type = self.detect_script_type(script) if script_type == ".py": runner_config = self.settings.get("selenium-tools").get("nose") elif script_type == ".jar" or script_type == ".java": runner_config = self.settings.get("selenium-tools").get("junit") else: raise ValueError("Unsupported script type: %s" % script_type) if self.runner_working_dir is None: self.runner_working_dir = self.engine.create_artifact(runner_config.get("working-dir", "classes"), "") self._cp_resource_files(self.runner_working_dir) return [os.path.basename(self.runner_working_dir)] def __tests_from_requests(self): filename = self.engine.create_artifact("test_requests", ".py") nose_test = SeleniumScriptBuilder(self.scenario, self.log) if self.virtual_display: nose_test.window_size=self.virtual_display.size nose_test.scenario = self.scenario nose_test.gen_test_case() nose_test.save(filename) return filename
class SumoEnvironment(gym.Env): """ SUMO Environment for Traffic Signal Control :param net_file: (str) SUMO .net.xml file :param route_file: (str) SUMO .rou.xml file :param out_csv_name: (Optional[str]) name of the .csv output with simulation results. If None no output is generated :param use_gui: (bool) Wheter to run SUMO simulation with GUI visualisation :param virtual_display: (Optional[Tuple[int,int]]) Resolution of a virtual display for rendering :param begin_time: (int) The time step (in seconds) the simulation starts :param num_seconds: (int) Number of simulated seconds on SUMO. The time in seconds the simulation must end. :param max_depart_delay: (int) Vehicles are discarded if they could not be inserted after max_depart_delay seconds :param delta_time: (int) Simulation seconds between actions :param min_green: (int) Minimum green time in a phase :param max_green: (int) Max green time in a phase :single_agent: (bool) If true, it behaves like a regular gym.Env. Else, it behaves like a MultiagentEnv (https://github.com/ray-project/ray/blob/master/python/ray/rllib/env/multi_agent_env.py) :sumo_seed: (int/string) Random seed for sumo. If 'random' it uses a randomly chosen seed. :fixed_ts: (bool) If true, it will follow the phase configuration in the route_file and ignore the actions. :sumo_warnings: (bool) If False, remove SUMO warnings in the terminal """ CONNECTION_LABEL = 0 # For traci multi-client support def __init__( self, net_file: str, route_file: str, out_csv_name: Optional[str] = None, use_gui: bool = False, virtual_display: Optional[Tuple[int,int]] = None, begin_time: int = 0, num_seconds: int = 20000, max_depart_delay: int = 100000, time_to_teleport: int = -1, delta_time: int = 5, yellow_time: int = 2, min_green: int = 5, max_green: int = 50, single_agent: bool = False, sumo_seed: Union[str,int] = 'random', fixed_ts: bool = False, sumo_warnings: bool = True, ): self._net = net_file self._route = route_file self.use_gui = use_gui if self.use_gui: self._sumo_binary = sumolib.checkBinary('sumo-gui') else: self._sumo_binary = sumolib.checkBinary('sumo') self.virtual_display = virtual_display assert delta_time > yellow_time, "Time between actions must be at least greater than yellow time." self.begin_time = begin_time self.sim_max_time = num_seconds self.delta_time = delta_time # seconds on sumo at each step self.max_depart_delay = max_depart_delay # Max wait time to insert a vehicle self.time_to_teleport = time_to_teleport self.min_green = min_green self.max_green = max_green self.yellow_time = yellow_time self.single_agent = single_agent self.sumo_seed = sumo_seed self.fixed_ts = fixed_ts self.sumo_warnings = sumo_warnings self.label = str(SumoEnvironment.CONNECTION_LABEL) SumoEnvironment.CONNECTION_LABEL += 1 self.sumo = None if LIBSUMO: traci.start([sumolib.checkBinary('sumo'), '-n', self._net]) # Start only to retrieve traffic light information conn = traci else: traci.start([sumolib.checkBinary('sumo'), '-n', self._net], label='init_connection'+self.label) conn = traci.getConnection('init_connection'+self.label) self.ts_ids = list(conn.trafficlight.getIDList()) self.traffic_signals = {ts: TrafficSignal(self, ts, self.delta_time, self.yellow_time, self.min_green, self.max_green, self.begin_time, conn) for ts in self.ts_ids} conn.close() self.vehicles = dict() self.reward_range = (-float('inf'), float('inf')) self.metadata = {} self.spec = EnvSpec('SUMORL-v0') self.run = 0 self.metrics = [] self.out_csv_name = out_csv_name self.observations = {ts: None for ts in self.ts_ids} self.rewards = {ts: None for ts in self.ts_ids} def _start_simulation(self): sumo_cmd = [self._sumo_binary, '-n', self._net, '-r', self._route, '--max-depart-delay', str(self.max_depart_delay), '--waiting-time-memory', '10000', '--time-to-teleport', str(self.time_to_teleport)] if self.begin_time > 0: sumo_cmd.append('-b {}'.format(self.begin_time)) if self.sumo_seed == 'random': sumo_cmd.append('--random') else: sumo_cmd.extend(['--seed', str(self.sumo_seed)]) if not self.sumo_warnings: sumo_cmd.append('--no-warnings') if self.use_gui: sumo_cmd.extend(['--start', '--quit-on-end']) if self.virtual_display is not None: sumo_cmd.extend(['--window-size', f'{self.virtual_display[0]},{self.virtual_display[1]}']) from pyvirtualdisplay.smartdisplay import SmartDisplay print("Creating a virtual display.") self.disp = SmartDisplay(size=self.virtual_display) self.disp.start() print("Virtual display started.") if LIBSUMO: traci.start(sumo_cmd) self.sumo = traci else: traci.start(sumo_cmd, label=self.label) self.sumo = traci.getConnection(self.label) if self.use_gui: self.sumo.gui.setSchema(traci.gui.DEFAULT_VIEW, "real world") def reset(self, seed: Optional[int] = None, **kwargs): if self.run != 0: self.close() self.save_csv(self.out_csv_name, self.run) self.run += 1 self.metrics = [] if seed is not None: self.sumo_seed = seed self._start_simulation() self.traffic_signals = {ts: TrafficSignal(self, ts, self.delta_time, self.yellow_time, self.min_green, self.max_green, self.begin_time, self.sumo) for ts in self.ts_ids} self.vehicles = dict() if self.single_agent: return self._compute_observations()[self.ts_ids[0]] else: return self._compute_observations() @property def sim_step(self): """ Return current simulation second on SUMO """ return self.sumo.simulation.getTime() def step(self, action): # No action, follow fixed TL defined in self.phases if action is None or action == {}: for _ in range(self.delta_time): self._sumo_step() else: self._apply_actions(action) self._run_steps() observations = self._compute_observations() rewards = self._compute_rewards() dones = self._compute_dones() info = self._compute_info() if self.single_agent: return observations[self.ts_ids[0]], rewards[self.ts_ids[0]], dones['__all__'], info else: return observations, rewards, dones, info def _run_steps(self): time_to_act = False while not time_to_act: self._sumo_step() for ts in self.ts_ids: self.traffic_signals[ts].update() if self.traffic_signals[ts].time_to_act: time_to_act = True def _apply_actions(self, actions): """ Set the next green phase for the traffic signals :param actions: If single-agent, actions is an int between 0 and self.num_green_phases (next green phase) If multiagent, actions is a dict {ts_id : greenPhase} """ if self.single_agent: if self.traffic_signals[self.ts_ids[0]].time_to_act: self.traffic_signals[self.ts_ids[0]].set_next_phase(actions) else: for ts, action in actions.items(): if self.traffic_signals[ts].time_to_act: self.traffic_signals[ts].set_next_phase(action) def _compute_dones(self): dones = {ts_id: False for ts_id in self.ts_ids} dones['__all__'] = self.sim_step > self.sim_max_time return dones def _compute_info(self): info = self._compute_step_info() self.metrics.append(info) return info def _compute_observations(self): self.observations.update({ts: self.traffic_signals[ts].compute_observation() for ts in self.ts_ids if self.traffic_signals[ts].time_to_act}) return {ts: self.observations[ts].copy() for ts in self.observations.keys() if self.traffic_signals[ts].time_to_act} def _compute_rewards(self): self.rewards.update({ts: self.traffic_signals[ts].compute_reward() for ts in self.ts_ids if self.traffic_signals[ts].time_to_act}) return {ts: self.rewards[ts] for ts in self.rewards.keys() if self.traffic_signals[ts].time_to_act} @property def observation_space(self): return self.traffic_signals[self.ts_ids[0]].observation_space @property def action_space(self): return self.traffic_signals[self.ts_ids[0]].action_space def observation_spaces(self, ts_id): return self.traffic_signals[ts_id].observation_space def action_spaces(self, ts_id): return self.traffic_signals[ts_id].action_space def _sumo_step(self): self.sumo.simulationStep() def _compute_step_info(self): return { 'step_time': self.sim_step, 'reward': self.traffic_signals[self.ts_ids[0]].last_reward, 'total_stopped': sum(self.traffic_signals[ts].get_total_queued() for ts in self.ts_ids), 'total_wait_time': sum(sum(self.traffic_signals[ts].get_waiting_time_per_lane()) for ts in self.ts_ids) } def close(self): if self.sumo is None: return if not LIBSUMO: traci.switch(self.label) traci.close() try: self.disp.stop() except AttributeError: pass self.sumo = None def __del__(self): self.close() def render(self, mode='human'): if self.virtual_display: #img = self.sumo.gui.screenshot(traci.gui.DEFAULT_VIEW, # f"temp/img{self.sim_step}.jpg", # width=self.virtual_display[0], # height=self.virtual_display[1]) img = self.disp.grab() if mode == 'rgb_array': return np.array(img) return img def save_csv(self, out_csv_name, run): if out_csv_name is not None: df = pd.DataFrame(self.metrics) Path(Path(out_csv_name).parent).mkdir(parents=True, exist_ok=True) df.to_csv(out_csv_name + '_conn{}_run{}'.format(self.label, run) + '.csv', index=False) # Below functions are for discrete state space def encode(self, state, ts_id): phase = int(np.where(state[:self.traffic_signals[ts_id].num_green_phases] == 1)[0]) min_green = state[self.traffic_signals[ts_id].num_green_phases] density_queue = [self._discretize_density(d) for d in state[self.traffic_signals[ts_id].num_green_phases + 1:]] # tuples are hashable and can be used as key in python dictionary return tuple([phase, min_green] + density_queue) def _discretize_density(self, density): return min(int(density*10), 9)
class BrowserInstance: def __init__(self, tor=False, tor_tries=10, save_directory="data", url_delay=10, random_pages=False, test=False): self.tor = tor self.tor_tries = tor_tries self.save_directory = save_directory self.url_delay = url_delay self.random_pages = random_pages self.sites = ["amazon", "apple", "nytimes", "google", "duckduckgo"] pathlib.Path(self.save_directory).mkdir(parents=True, exist_ok=True) self.display = SmartDisplay(backend='xephyr', visible=1, size=(1920, 1080)) self.display.start() self.firefox_profile_path = tempfile.mkdtemp() self.firefox_profile = webdriver.FirefoxProfile( self.firefox_profile_path) if self.tor: for i in range(self.tor_tries): try: self.socks_port = free_port() self.control_port = free_port() self.tor_data_dir = tempfile.mkdtemp() self.torrc = { 'ControlPort': str(self.control_port), 'SOCKSPort': str(self.socks_port), 'DataDirectory': self.tor_data_dir, 'EntryNodes': '{us}', 'ExitNodes': '{us}', 'StrictNodes': '1' } self.tor_process = launch_tor_with_config( config=self.torrc, tor_cmd="/usr/sbin/tor") except: print("Tor connection attempt {} failed.".format(i)) sys.stdout.flush() if i == self.tor_tries - 1: sys.exit() continue break self.firefox_profile.set_preference("network.proxy.type", 1) self.firefox_profile.set_preference("network.proxy.socks", "localhost") self.firefox_profile.set_preference("network.proxy.socks_port", self.socks_port) self.firefox_profile.set_preference("network.proxy.socks_version", 5) self.firefox_profile.update_preferences() self.driver = webdriver.Firefox(service_log_path=os.path.join( self.firefox_profile_path, "geckodriver.log"), firefox_profile=self.firefox_profile) self.driver.maximize_window() if test: self.driver.get("https://www.{}.com/".format( random.choice(self.sites))) time.sleep(self.url_delay) def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.cleanup() def cleanup(self): self.display.stop() shutil.rmtree(self.firefox_profile_path) if self.tor: self.tor_process.kill() shutil.rmtree(self.tor_data_dir) def print_ports(self): print("SOCKS Port: {}, Control Port: {}".format( self.socks_port, self.control_port)) def tar_and_hash(self, contents): tmp_tar_directory = tempfile.mkdtemp() archive_name = os.path.join(tmp_tar_directory, "tarball.txz") with tarfile.open(archive_name, "w:xz") as tar: tar.add(contents) h = hashlib.sha256() with open(archive_name, 'rb') as f: h.update(f.read()) archive_hash = h.hexdigest() shutil.copy( archive_name, os.path.join(self.save_directory, "{}.txz".format(archive_hash))) shutil.rmtree(tmp_tar_directory) return archive_hash def save_html(self): fd, path = tempfile.mkstemp() with open(path, "w") as f: f.write(self.driver.page_source) os.close(fd) archive_hash = self.tar_and_hash(path) os.remove(path) return archive_hash def save_page(self): pyautogui._pyautogui_x11._display = Xlib.display.Display( os.environ['DISPLAY']) tmp_page_directory = tempfile.mkdtemp() pyautogui.PAUSE = self.url_delay pyautogui.hotkey('alt', 'tab') pyautogui.hotkey('ctrl', 's') pyautogui.write(os.path.join(tmp_page_directory, "page")) pyautogui.press('enter') time.sleep(self.url_delay) archive_hash = self.tar_and_hash(tmp_page_directory) shutil.rmtree(tmp_page_directory) return archive_hash def scroll_page(self): height = 0 height_increment = 500 total_height = int( self.driver.execute_script("return document.body.scrollHeight")) while (height <= total_height): self.driver.execute_script("window.scrollTo({}, {});".format( height, height + height_increment)) time.sleep(2) height += height_increment total_height = int( self.driver.execute_script( "return document.body.scrollHeight")) def visit_random_page(self): if self.random_pages and random.choices([True, False], [0.25, 0.75])[0]: self.driver.get("https://www.{}.com/".format( random.choice(self.sites))) time.sleep(self.url_delay) def get_url(self, url): try: self.visit_random_page() self.driver.get(url) time.sleep(self.url_delay) self.scroll_page() self.url_tries_cound = 0 return BeautifulSoup(self.driver.page_source, "html.parser") except: print("URL Connection Error: {}".format(url)) sys.stdout.flush() return False def get_page_from_archive(self, archive_file): tmp_page_directory = tempfile.mkdtemp() os.chdir(tmp_page_directory) with tarfile.open(archive_file, "r:xz") as tar: tar.extractall(tmp_page_directory) url = glob.glob('**/page.html', recursive=True) if url: url = "file://" + tmp_page_directory + "/" + url[0] self.driver.get(url) s = BeautifulSoup(self.driver.page_source, "html.parser") else: s = False os.chdir(self.save_directory) shutil.rmtree(tmp_page_directory) return s
class SeleniumExecutor(ScenarioExecutor, WidgetProvider, FileLister): """ Selenium executor :type virtual_display: Display :type runner: AbstractTestRunner """ SELENIUM_DOWNLOAD_LINK = "http://selenium-release.storage.googleapis.com/{version}/" \ "selenium-server-standalone-{version}.0.jar" SELENIUM_VERSION = "2.53" JUNIT_DOWNLOAD_LINK = "http://search.maven.org/remotecontent?filepath=junit/junit/" \ "{version}/junit-{version}.jar" JUNIT_VERSION = "4.12" JUNIT_MIRRORS_SOURCE = "http://search.maven.org/solrsearch/select?q=g%3A%22junit%22%20AND%20a%3A%22" \ "junit%22%20AND%20v%3A%22{version}%22&rows=20&wt=json".format(version=JUNIT_VERSION) HAMCREST_DOWNLOAD_LINK = "http://search.maven.org/remotecontent?filepath=org/hamcrest/hamcrest-core" \ "/1.3/hamcrest-core-1.3.jar" JSON_JAR_DOWNLOAD_LINK = "http://search.maven.org/remotecontent?filepath=org/json/json/20160810/json-20160810.jar" SUPPORTED_TYPES = [".py", ".jar", ".java"] SHARED_VIRTUAL_DISPLAY = {} def __init__(self): super(SeleniumExecutor, self).__init__() self.additional_env = {} self.virtual_display = None self.end_time = None self.runner = None self.reader = None self.report_file = None self.runner_working_dir = None self.scenario = None self.script = None self.self_generated_script = False self.generated_methods = BetterDict() def set_virtual_display(self): display_conf = self.settings.get("virtual-display") if display_conf: if is_windows(): self.log.warning( "Cannot have virtual display on Windows, ignoring") else: if self.engine in SeleniumExecutor.SHARED_VIRTUAL_DISPLAY: self.virtual_display = SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[ self.engine] else: width = display_conf.get("width", 1024) height = display_conf.get("height", 768) self.virtual_display = Display(size=(width, height)) msg = "Starting virtual display[%s]: %s" self.log.info(msg, self.virtual_display.size, self.virtual_display.new_display_var) self.virtual_display.start() SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[ self.engine] = self.virtual_display def free_virtual_display(self): if self.virtual_display and self.virtual_display.is_alive(): self.virtual_display.stop() if self.engine in SeleniumExecutor.SHARED_VIRTUAL_DISPLAY: del SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[self.engine] def get_script_path(self, scenario=None): if scenario: return super(SeleniumExecutor, self).get_script_path(scenario) else: return self.engine.find_file(self.script) def _create_runner(self, working_dir, report_file): script_path = self.get_script_path() script_type = self.detect_script_type(script_path) runner_config = BetterDict() if script_type == ".py": runner_class = NoseTester runner_config.merge( self.settings.get("selenium-tools").get("nose")) else: # script_type == ".jar" or script_type == ".java": runner_class = JUnitTester runner_config.merge( self.settings.get("selenium-tools").get("junit")) runner_config['props-file'] = self.engine.create_artifact( "customrunner", ".properties") runner_config["script-type"] = script_type runner_config["working-dir"] = working_dir runner_config.get("artifacts-dir", self.engine.artifacts_dir) runner_config.get("report-file", report_file) runner_config.get("stdout", self.engine.create_artifact("junit", ".out")) runner_config.get("stderr", self.engine.create_artifact("junit", ".err")) return runner_class(runner_config, self) def _create_reader(self, report_file): return LoadSamplesReader(report_file, self.log, self.generated_methods) def prepare(self): self.set_virtual_display() self.scenario = self.get_scenario() self._verify_script() self.runner_working_dir = self.engine.create_artifact("classes", "") self.report_file = self.engine.create_artifact("selenium_tests_report", ".ldjson") self.runner = self._create_runner(self.runner_working_dir, self.report_file) self._cp_resource_files(self.runner_working_dir) self.runner.prepare() self.reader = self._create_reader(self.report_file) if isinstance(self.engine.aggregator, ConsolidatingAggregator): self.engine.aggregator.add_underling(self.reader) def _verify_script(self): if Scenario.SCRIPT in self.scenario and self.scenario.get( Scenario.SCRIPT): self.script = self.scenario.get(Scenario.SCRIPT) elif "requests" in self.scenario: self.script = self.__tests_from_requests() self.self_generated_script = True else: raise ValueError( "Nothing to test, no requests were provided in scenario") def _cp_resource_files(self, runner_working_dir): script = self.get_script_path() if os.path.isdir(script): shutil.copytree(script, runner_working_dir) else: os.makedirs(runner_working_dir) if self.self_generated_script: shutil.move(script, runner_working_dir) else: script_type = self.detect_script_type(script) script_name = os.path.basename(script) if script_type == ".py" and not script_name.lower().startswith( 'test'): target_name = 'test_' + script_name msg = "Script '%s' won't be discovered by nosetests, renaming script to %s" self.log.warning(msg, script_name, target_name) else: target_name = script_name target_path = os.path.join(runner_working_dir, target_name) shutil.copy2(script, target_path) @staticmethod def detect_script_type(script_path): if not isinstance(script_path, string_types) and not isinstance( script_path, text_type): raise ValueError( "Nothing to test, no files were provided in scenario") if not os.path.exists(script_path): raise ValueError("Script %s doesn't exist" % script_path) file_types = set() if os.path.isfile(script_path): # regular file received file_types.add(os.path.splitext(script_path)[1].lower()) else: # dir received: check contained files for file_name in get_files_recursive(script_path): file_types.add(os.path.splitext(file_name)[1].lower()) if '.java' in file_types: file_ext = '.java' elif '.py' in file_types: file_ext = '.py' elif '.jar' in file_types: file_ext = '.jar' else: raise ValueError("Unsupported script type: %s" % script_path) return file_ext def startup(self): """ Start runner :return: """ self.start_time = time.time() self.runner.env = self.additional_env self.runner.run_tests() def check_virtual_display(self): if self.virtual_display: if not self.virtual_display.is_alive(): self.log.info("Virtual display out: %s", self.virtual_display.stdout) self.log.warning("Virtual display err: %s", self.virtual_display.stderr) raise RuntimeError("Virtual display failed: %s" % self.virtual_display.return_code) def check(self): """ check if test completed :return: """ if self.widget: self.widget.update() self.check_virtual_display() return self.runner.is_finished() def report_test_duration(self): if self.start_time: self.end_time = time.time() self.log.debug("Selenium tests ran for %s seconds", self.end_time - self.start_time) def shutdown(self): """ shutdown test_runner :return: """ self.runner.shutdown() self.report_test_duration() def post_process(self): self.free_virtual_display() if self.reader and not self.reader.read_records: raise RuntimeWarning("Empty results, most likely Selenium failed") def get_widget(self): if not self.widget: self.widget = SeleniumWidget(self.script, self.runner.settings.get("stdout")) return self.widget def resource_files(self): self.scenario = self.get_scenario() self._verify_script() script_path = self.get_script_path() resources = [] if script_path is not None: resources.append(script_path) return resources def __tests_from_requests(self): filename = self.engine.create_artifact("test_requests", ".py") wdlog = self.engine.create_artifact('webdriver', '.log') nose_test = SeleniumScriptBuilder(self.scenario, self.log, wdlog) if self.virtual_display: nose_test.window_size = self.virtual_display.size self.generated_methods.merge(nose_test.gen_test_case()) nose_test.save(filename) return filename
class Hangouts(NavigationHelpers): """ Base class that provide all bunch of options. """ # TODO: how to show self.display, self.browser and self.hangout_id in # docs? def __init__(self, browser="chrome", executable_path=None): """ Initialization does two things: 1. Makes sure that there is active X session. 2. Starts browser. On initialization it stats X session if can't find 'DISPLAY' in os.environ. For this purposes used *pyvirtualdisplay* package. For handling browser used seleniumwrapper library. """ # lets start display in case if no is available self.hangout_id = None self.display = None if not os.environ.get('DISPLAY'): self.display = SmartDisplay() self.display.start() kwargs = {} if browser == "chrome": kwargs['executable_path'] = executable_path or CHROMEDRV_PATH self.browser = selwrap.create(browser, **kwargs) self.video = VideoSettings(self) self.microphone = MicrophoneSettings(self) self.audio = AudioSettings(self) self.bandwidth = BandwidthSettings(self) def start(self, onair=False): """ Start new hangout. """ if not self.browser.current_url.startswith(URLS.hangouts_active_list): self.browser.get(URLS.hangouts_active_list) self.browser.by_class('opd').click(timeout=0.5) # G+ opens new window for new hangout, so we need to switch selenium to # it # waiting until new window appears while len(self.browser.window_handles) <= 1: sleep(0.2) # XXX: add waiting for second window to open self.browser.close() # closing old window # TODO: 'Google+' title self.browser.switch_to_window(self.browser.window_handles[0]) self.click_cancel_button_if_there_is_one(timeout=30) # setting hangout id property self.hangout_id = self.browser.current_url.replace( URLS.hangout_session_base, '', 1).split('?', 1)[0] def connect(self, hangout_id): """ Connect to an existing hangout. Takes id of targeted hangout as argument """ self.hangout_id = hangout_id self.browser.get(URLS.hangout_session_base + hangout_id) # there may be a big delay before 'Join' button appears, so we need # to add longer timeout for this self.browser.by_text('Join', timeout=60).click(timeout=0.5) def login(self, username=None, password=None, otp=None): """ Log into google plus account. *opt* argument is one time password and is optional, set it only if you're 2-factor authorization """ # Open login form and sing in with credentials self.browser.get(URLS.service_login) self.browser.by_id('Email').send_keys(username) self.browser.by_id('Passwd').send_keys(password) self.browser.by_id('signIn').click(timeout=0.5) # filling up one time password if provides if otp: self.browser.by_id('smsUserPin').send_keys(otp) self.browser.by_id('smsVerifyPin').click(timeout=0.5) # checking if log in was successful if not self.is_logged_in: raise LoginError( 'Wasn\'t able to login. Check if credentials are correct' 'and make sure that you have G+ account activated') def invite(self, participants): """ Invite person or circle to hangout >>> hangout.invite("*****@*****.**") >>> hangout.invite(["*****@*****.**", "Circle Name A"]) """ self.click_cancel_button_if_there_is_one() if not any(isinstance(participants, i) for i in (list, tuple)): participants = [ participants, ] # click on Invite People button self.click_menu_element('//div[@aria-label="Invite People"]') input = self.browser.xpath( '//input[@placeholder="+ Add names, circles, or email addresses"]') input.send_keys("\n".join(participants) + "\n\n") self.browser.by_text('Invite').click(timeout=0.5) def participants(self): """ Returns list of current participants >>> hangout.participants() ['John Doe', ...] """ xpath = '//div[@aria-label="Video call participants"]/div' participants = self.browser.xpath(xpath, eager=True) return [ p.get_attribute('aria-label').split('Open menu for ')[1] for p in participants ] def leave_call(self): """ Leave hangout. EQ to click on "Leave call" button. """ self.click_menu_element('//div[@aria-label="Leave call"]') def __del__(self): # leaving the call first self.browser.silent = True try: self.leave_call() except: pass try: self.browser.quit() finally: if self.display is not None: self.display.stop()
class SeleniumExecutor(ScenarioExecutor, WidgetProvider, FileLister): """ Selenium executor :type virtual_display: Display :type runner: AbstractTestRunner """ SELENIUM_DOWNLOAD_LINK = "http://selenium-release.storage.googleapis.com/{version}/" \ "selenium-server-standalone-{version}.0.jar" SELENIUM_VERSION = "2.53" JUNIT_DOWNLOAD_LINK = "http://search.maven.org/remotecontent?filepath=junit/junit/{version}/junit-{version}.jar" JUNIT_VERSION = "4.12" JUNIT_MIRRORS_SOURCE = "http://search.maven.org/solrsearch/select?q=g%3A%22junit%22%20AND%20a%3A%22junit%22%20" \ "AND%20v%3A%22{version}%22&rows=20&wt=json".format(version=JUNIT_VERSION) HAMCREST_DOWNLOAD_LINK = "https://hamcrest.googlecode.com/files/hamcrest-core-1.3.jar" SUPPORTED_TYPES = [".py", ".jar", ".java"] SHARED_VIRTUAL_DISPLAY = {} def __init__(self): super(SeleniumExecutor, self).__init__() self.additional_env = {} self.virtual_display = None self.start_time = None self.end_time = None self.runner = None self.widget = None self.reader = None self.kpi_file = None self.err_jtl = None self.runner_working_dir = None self.scenario = None def set_virtual_display(self): display_conf = self.settings.get("virtual-display") if display_conf: if is_windows(): self.log.warning("Cannot have virtual display on Windows, ignoring") else: if self.engine in SeleniumExecutor.SHARED_VIRTUAL_DISPLAY: self.virtual_display = SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[self.engine] else: width = display_conf.get("width", 1024) height = display_conf.get("height", 768) self.virtual_display = Display(size=(width, height)) msg = "Starting virtual display[%s]: %s" self.log.info(msg, self.virtual_display.size, self.virtual_display.new_display_var) self.virtual_display.start() SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[self.engine] = self.virtual_display def free_virtual_display(self): if self.virtual_display and self.virtual_display.is_alive(): self.virtual_display.stop() if self.engine in SeleniumExecutor.SHARED_VIRTUAL_DISPLAY: del SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[self.engine] def _get_script_path(self): script = self.scenario.get(Scenario.SCRIPT) if not script: return None return self.engine.find_file(script) def prepare(self): self.set_virtual_display() self.scenario = self.get_scenario() self._verify_script() self.kpi_file = self.engine.create_artifact("selenium_tests_report", ".csv") self.err_jtl = self.engine.create_artifact("selenium_tests_err", ".xml") script_path = self._get_script_path() script_type = self.detect_script_type(script_path) runner_config = BetterDict() if script_type == ".py": runner_class = NoseTester runner_config.merge(self.settings.get("selenium-tools").get("nose")) else: # script_type == ".jar" or script_type == ".java": runner_class = JUnitTester runner_config.merge(self.settings.get("selenium-tools").get("junit")) runner_config['props-file'] = self.engine.create_artifact("customrunner", ".properties") runner_config["script-type"] = script_type if self.runner_working_dir is None: self.runner_working_dir = self.engine.create_artifact(runner_config.get("working-dir", "classes"), "") runner_config["working-dir"] = self.runner_working_dir runner_config.get("artifacts-dir", self.engine.artifacts_dir) runner_config.get("working-dir", self.runner_working_dir) runner_config.get("report-file", self.kpi_file) runner_config.get("err-file", self.err_jtl) runner_config.get("stdout", self.engine.create_artifact("junit", ".out")) runner_config.get("stderr", self.engine.create_artifact("junit", ".err")) self._cp_resource_files(self.runner_working_dir) self.runner = runner_class(runner_config, self) self.runner.prepare() self.reader = JTLReader(self.kpi_file, self.log, self.err_jtl) if isinstance(self.engine.aggregator, ConsolidatingAggregator): self.engine.aggregator.add_underling(self.reader) def _verify_script(self): if not self.scenario.get(Scenario.SCRIPT): if self.scenario.get("requests"): self.scenario[Scenario.SCRIPT] = self.__tests_from_requests() else: raise RuntimeError("Nothing to test, no requests were provided in scenario") def _cp_resource_files(self, runner_working_dir): """ :return: """ script = self._get_script_path() if script is not None: if os.path.isdir(script): shutil.copytree(script, runner_working_dir) else: os.makedirs(runner_working_dir) shutil.copy2(script, runner_working_dir) @staticmethod def detect_script_type(script_path): """ checks if script is java or python if it's folder or single script :param script_path: str :return: """ if not isinstance(script_path, string_types) and not isinstance(script_path, text_type): raise ValueError("Nothing to test, no files were provided in scenario") if not os.path.exists(script_path): raise ValueError("Script %s doesn't exist" % script_path) file_types = set() if os.path.isfile(script_path): # regular file received file_types.add(os.path.splitext(script_path)[1].lower()) else: # dir received: check files for walk_rec in os.walk(script_path): for file_name in walk_rec[2]: file_types.add(os.path.splitext(file_name)[1].lower()) if '.java' in file_types: file_ext = '.java' elif '.py' in file_types: file_ext = '.py' elif '.jar' in file_types: file_ext = '.jar' else: raise ValueError("Unsupported script type: %s" % script_path) return file_ext def startup(self): """ Start runner :return: """ self.start_time = time.time() self.runner.env = self.additional_env self.runner.run_tests() def check(self): """ check if test completed :return: """ if self.widget: self.widget.update() if self.virtual_display: if not self.virtual_display.is_alive(): self.log.info("Virtual display out: %s", self.virtual_display.stdout) self.log.warning("Virtual display err: %s", self.virtual_display.stderr) raise RuntimeError("Virtual display failed: %s" % self.virtual_display.return_code) return self.runner.is_finished() def shutdown(self): """ shutdown test_runner :return: """ self.runner.shutdown() if self.start_time: self.end_time = time.time() self.log.debug("Selenium tests ran for %s seconds", self.end_time - self.start_time) def post_process(self): self.free_virtual_display() if self.reader and not self.reader.read_records: raise RuntimeWarning("Empty results, most likely Selenium failed") def get_widget(self): if not self.widget: self.widget = SeleniumWidget(self.scenario.get(Scenario.SCRIPT), self.runner.settings.get("stdout")) return self.widget def resource_files(self): if not self.scenario: self.scenario = self.get_scenario() if Scenario.SCRIPT not in self.scenario: return [] script_path = self._get_script_path() if os.path.isdir(script_path): files = next(os.walk(script_path)) resources = [os.path.join(files[0], f) for f in files[2]] else: resources = [script_path] return resources def __tests_from_requests(self): filename = self.engine.create_artifact("test_requests", ".py") nose_test = SeleniumScriptBuilder(self.scenario, self.log) if self.virtual_display: nose_test.window_size = self.virtual_display.size nose_test.gen_test_case() nose_test.save(filename) return filename
class SeleniumExecutor(ScenarioExecutor, WidgetProvider, FileLister): """ Selenium executor :type virtual_display: Display :type runner: AbstractTestRunner """ SELENIUM_DOWNLOAD_LINK = "http://selenium-release.storage.googleapis.com/{version}/" \ "selenium-server-standalone-{version}.0.jar" SELENIUM_VERSION = "2.53" JUNIT_DOWNLOAD_LINK = "http://search.maven.org/remotecontent?filepath=junit/junit/" \ "{version}/junit-{version}.jar" JUNIT_VERSION = "4.12" JUNIT_MIRRORS_SOURCE = "http://search.maven.org/solrsearch/select?q=g%3A%22junit%22%20AND%20a%3A%22" \ "junit%22%20AND%20v%3A%22{version}%22&rows=20&wt=json".format(version=JUNIT_VERSION) HAMCREST_DOWNLOAD_LINK = "http://search.maven.org/remotecontent?filepath=org/hamcrest/hamcrest-core" \ "/1.3/hamcrest-core-1.3.jar" JSON_JAR_DOWNLOAD_LINK = "http://search.maven.org/remotecontent?filepath=org/json/json/20160810/json-20160810.jar" SUPPORTED_TYPES = ["python-nose", "java-junit", "ruby-rspec"] SHARED_VIRTUAL_DISPLAY = {} def __init__(self): super(SeleniumExecutor, self).__init__() self.additional_env = {} self.virtual_display = None self.end_time = None self.runner = None self.report_file = None self.scenario = None self.script = None self.self_generated_script = False self.generated_methods = BetterDict() self.runner_working_dir = None def set_virtual_display(self): display_conf = self.settings.get("virtual-display") if display_conf: if is_windows(): self.log.warning("Cannot have virtual display on Windows, ignoring") else: if self.engine in SeleniumExecutor.SHARED_VIRTUAL_DISPLAY: self.virtual_display = SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[self.engine] else: width = display_conf.get("width", 1024) height = display_conf.get("height", 768) self.virtual_display = Display(size=(width, height)) msg = "Starting virtual display[%s]: %s" self.log.info(msg, self.virtual_display.size, self.virtual_display.new_display_var) self.virtual_display.start() SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[self.engine] = self.virtual_display def free_virtual_display(self): if self.virtual_display and self.virtual_display.is_alive(): self.virtual_display.stop() if self.engine in SeleniumExecutor.SHARED_VIRTUAL_DISPLAY: del SeleniumExecutor.SHARED_VIRTUAL_DISPLAY[self.engine] def get_script_path(self, scenario=None): if scenario: return super(SeleniumExecutor, self).get_script_path(scenario) else: return self.engine.find_file(self.script) def get_runner_working_dir(self): if self.runner_working_dir is None: self.runner_working_dir = self.engine.create_artifact("classes", "") return self.runner_working_dir def _create_runner(self, report_file): script_path = self.get_script_path() script_type = self.detect_script_type(script_path) runner_config = BetterDict() if script_type == "python-nose": runner_class = NoseTester runner_config.merge(self.settings.get("selenium-tools").get("nose")) elif script_type == "java-junit": runner_class = JUnitTester runner_config.merge(self.settings.get("selenium-tools").get("junit")) runner_config['working-dir'] = self.get_runner_working_dir() runner_config['props-file'] = self.engine.create_artifact("customrunner", ".properties") elif script_type == "ruby-rspec": runner_class = RSpecTester elif script_type == "js-mocha": runner_class = MochaTester else: raise ValueError("Unsupported script type: %s" % script_type) runner_config["script"] = script_path runner_config["script-type"] = script_type runner_config["artifacts-dir"] = self.engine.artifacts_dir runner_config["report-file"] = report_file runner_config["stdout"] = self.engine.create_artifact("selenium", ".out") runner_config["stderr"] = self.engine.create_artifact("selenium", ".err") return runner_class(runner_config, self) def _register_reader(self, report_file): if self.engine.is_functional_mode(): reader = FuncSamplesReader(report_file, self.log, self.generated_methods) if isinstance(self.engine.aggregator, FunctionalAggregator): self.engine.aggregator.add_underling(reader) else: reader = LoadSamplesReader(report_file, self.log, self.generated_methods) if isinstance(self.engine.aggregator, ConsolidatingAggregator): self.engine.aggregator.add_underling(reader) return reader def prepare(self): self.set_virtual_display() self.scenario = self.get_scenario() self.__setup_script() self.report_file = self.engine.create_artifact("selenium_tests_report", ".ldjson") self.runner = self._create_runner(self.report_file) self.runner.prepare() self.reader = self._register_reader(self.report_file) def __setup_script(self): if Scenario.SCRIPT in self.scenario and self.scenario.get(Scenario.SCRIPT): self.script = self.scenario.get(Scenario.SCRIPT) elif "requests" in self.scenario: self.script = self.__tests_from_requests() self.self_generated_script = True else: raise ValueError("Nothing to test, no requests were provided in scenario") def detect_script_type(self, script_path): if not isinstance(script_path, string_types) and not isinstance(script_path, text_type): raise ValueError("Nothing to test, no files were provided in scenario") if not os.path.exists(script_path): raise ValueError("Script %s doesn't exist" % script_path) if "language" in self.execution: lang = self.execution["language"] if lang not in self.SUPPORTED_TYPES: tmpl = "Language '%s' is not supported. Supported languages are: %s" raise ValueError(tmpl % (lang, self.SUPPORTED_TYPES)) self.log.debug("Using script type: %s", lang) return lang file_types = set() if os.path.isfile(script_path): # regular file received file_types.add(os.path.splitext(script_path)[1].lower()) else: # dir received: check contained files for file_name in get_files_recursive(script_path): file_types.add(os.path.splitext(file_name)[1].lower()) if '.java' in file_types or '.jar' in file_types: script_type = 'java-junit' elif '.py' in file_types: script_type = 'python-nose' elif '.rb' in file_types: script_type = 'ruby-rspec' elif '.js' in file_types: script_type = 'js-mocha' else: raise ValueError("Unsupported script type: %s" % script_path) self.log.debug("Detected script type: %s", script_type) return script_type def startup(self): """ Start runner :return: """ self.start_time = time.time() self.runner.env = self.additional_env self.runner.run_tests() def check_virtual_display(self): if self.virtual_display: if not self.virtual_display.is_alive(): self.log.info("Virtual display out: %s", self.virtual_display.stdout) self.log.warning("Virtual display err: %s", self.virtual_display.stderr) raise RuntimeError("Virtual display failed: %s" % self.virtual_display.return_code) def check(self): """ check if test completed :return: """ if self.widget: self.widget.update() self.check_virtual_display() return self.runner.is_finished() def report_test_duration(self): if self.start_time: self.end_time = time.time() self.log.debug("Selenium tests ran for %s seconds", self.end_time - self.start_time) def shutdown(self): """ shutdown test_runner :return: """ self.runner.shutdown() self.report_test_duration() def post_process(self): self.free_virtual_display() def has_results(self): if self.reader and self.reader.read_records: return True else: return False def get_widget(self): if not self.widget: self.widget = SeleniumWidget(self.script, self.runner.settings.get("stdout")) return self.widget def resource_files(self): self.scenario = self.get_scenario() self.__setup_script() script_path = self.get_script_path() resources = [] if script_path is not None: resources.append(script_path) return resources def __tests_from_requests(self): filename = self.engine.create_artifact("test_requests", ".py") wdlog = self.engine.create_artifact('webdriver', '.log') nose_test = SeleniumScriptBuilder(self.scenario, self.log, wdlog) if self.virtual_display: nose_test.window_size = self.virtual_display.size self.generated_methods.merge(nose_test.build_source_code()) nose_test.save(filename) return filename
if args.virtual: try: from pyvirtualdisplay.smartdisplay import SmartDisplay except ImportError: print "Please install the Python pyvirtualdisplay module." print " sudo pip install pyvirtualdisplay" sys.exit(-1) disp = None try: disp = SmartDisplay(visible=0, bgcolor='black').start() atexit.register(disp.stop) except: if disp: disp.stop() # Start up the web browser and run the tests. # ---------------------------------------------------------------------------- try: from selenium import webdriver except ImportError: print "Please install the Python selenium module." print " sudo pip install selenium" sys.exit(-1) driver_arguments = {} if args.browser == "Chrome": import tempfile, shutil
class Hangouts(NavigationHelpers): """ Base class that provide all bunch of options. """ # TODO: how to show self.display, self.browser and self.hangout_id in # docs? def __init__(self, browser="chrome", executable_path=None): """ Initialization does two things: 1. Makes sure that there is active X session. 2. Starts browser. On initialization it stats X session if can't find 'DISPLAY' in os.environ. For this purposes used *pyvirtualdisplay* package. For handling browser used seleniumwrapper library. """ # lets start display in case if no is available self.hangout_id = None self.display = None if not os.environ.get('DISPLAY'): self.display = SmartDisplay() self.display.start() kwargs = {} if browser == "chrome": kwargs['executable_path'] = executable_path or CHROMEDRV_PATH self.browser = selwrap.create(browser, **kwargs) self.video = VideoSettings(self) self.microphone = MicrophoneSettings(self) self.audio = AudioSettings(self) self.bandwidth = BandwidthSettings(self) def start(self, onair=False): """ Start new hangout. """ if not self.browser.current_url.startswith(URLS.hangouts_active_list): self.browser.get(URLS.hangouts_active_list) self.browser.by_class('opd').click(timeout=0.5) # G+ opens new window for new hangout, so we need to switch selenium to # it # waiting until new window appears while len(self.browser.window_handles) <= 1: sleep(0.2) # XXX: add waiting for second window to open self.browser.close() # closing old window # TODO: 'Google+' title self.browser.switch_to_window(self.browser.window_handles[0]) self.click_cancel_button_if_there_is_one(timeout=30) # setting hangout id property self.hangout_id = self.browser.current_url.replace( URLS.hangout_session_base, '', 1).split('?', 1)[0] def connect(self, hangout_id): """ Connect to an existing hangout. Takes id of targeted hangout as argument """ self.hangout_id = hangout_id self.browser.get(URLS.hangout_session_base + hangout_id) # there may be a big delay before 'Join' button appears, so we need # to add longer timeout for this self.browser.by_text('Join', timeout=60).click(timeout=0.5) def login(self, username=None, password=None, otp=None): """ Log into google plus account. *opt* argument is one time password and is optional, set it only if you're 2-factor authorization """ # Open login form and sing in with credentials self.browser.get(URLS.service_login) self.browser.by_id('Email').send_keys(username) self.browser.by_id('Passwd').send_keys(password) self.browser.by_id('signIn').click(timeout=0.5) # filling up one time password if provides if otp: self.browser.by_id('smsUserPin').send_keys(otp) self.browser.by_id('smsVerifyPin').click(timeout=0.5) # checking if log in was successful if not self.is_logged_in: raise LoginError( 'Wasn\'t able to login. Check if credentials are correct' 'and make sure that you have G+ account activated') def invite(self, participants): """ Invite person or circle to hangout >>> hangout.invite("*****@*****.**") >>> hangout.invite(["*****@*****.**", "Circle Name A"]) """ self.click_cancel_button_if_there_is_one() if not any(isinstance(participants, i) for i in (list, tuple)): participants = [participants, ] # click on Invite People button self.click_menu_element('//div[@aria-label="Invite People"]') input = self.browser.xpath( '//input[@placeholder="+ Add names, circles, or email addresses"]') input.send_keys("\n".join(participants) + "\n\n") self.browser.by_text('Invite').click(timeout=0.5) def participants(self): """ Returns list of current participants >>> hangout.participants() ['John Doe', ...] """ xpath = '//div[@aria-label="Video call participants"]/div' participants = self.browser.xpath(xpath, eager=True) return [p.get_attribute('aria-label').split('Open menu for ')[1] for p in participants] def leave_call(self): """ Leave hangout. EQ to click on "Leave call" button. """ self.click_menu_element('//div[@aria-label="Leave call"]') def __del__(self): # leaving the call first self.browser.silent = True try: self.leave_call() except: pass try: self.browser.quit() finally: if self.display is not None: self.display.stop()