def test_removing(browser: webdriver.Remote): browser.get('https://the-internet.herokuapp.com/add_remove_elements/') btn_add = browser.find_element_by_xpath('//button[text()="Add Element"]') max_add = random.randint(2, 15) print(f"will add button for {max_add} times ") for x in range(0, max_add): btn_add.click() time.sleep( 0.1 ) # make little bit visible ahaha :D believe me you wont see it, try to remark btns_delete = browser.find_elements_by_css_selector('#elements button') print('total btns_delete: ', len(btns_delete)) print(btns_delete) for btn_delete in btns_delete: btn_delete.click() time.sleep( 0.1 ) # make little bit visible ahaha :D believe me you wont see it, try to remark # before getting not found items, we should reduce implicit time to make selenium wait shorter browser.implicitly_wait(1) btns_delete = browser.find_elements_by_css_selector('#elements button') assert len(btns_delete) == 0
def test_adding(browser: webdriver.Remote): browser.get('https://the-internet.herokuapp.com/add_remove_elements/') btn_add = browser.find_element_by_xpath('//button[text()="Add Element"]') # Check default state browser.implicitly_wait( 0.3 ) # before getting not found items, we should reduce implicit time to make selenium wait shorter btns_delete = browser.find_elements_by_css_selector('#elements button') assert len(btns_delete) == 0 browser.implicitly_wait(5) # restore it btn_add.click() btns_delete = browser.find_elements_by_css_selector('#elements button') assert len(btns_delete) > 0
def _load_family_urls(driver: Remote, url: str): page_url_pattern = url + "?page={}" result = [] page_number = 1 page_count = 1 while page_number <= page_count: page_url = page_url_pattern.format(page_number) driver.get(page_url) div_element = driver.find_element_by_css_selector( "div.breadcrumb-collection div.breadcrumb_text") page_count = int( re.match(".*Page \d+ of (?P<page_count>\d+)$", div_element.get_property("innerText"), re.IGNORECASE).group("page_count")) a_elements = driver.find_elements_by_css_selector( "div.product-list div.product-wrap a.product-info__caption") for a_element in a_elements: result.append(a_element.get_attribute("href")) logger.debug("Loaded %d products family URLs from '%s'", len(a_elements), page_url) page_number += 1 return result
def scrape_contents(driver: Remote) -> List[dict]: """ 文章コンテンツのURL、タイトル、概要、スキの数を含むdictのリストを取得する。 """ contents = [] # 取得したコンテンツを格納するリスト。 # コンテンツを表すdiv要素について反復する。 for div in driver.find_elements_by_css_selector('.o-timeline__item'): a = div.find_element_by_css_selector('a') try: description = div.find_element_by_css_selector('p').text except NoSuchElementException: description = '' # 画像コンテンツなどp要素がない場合は空文字にする。 # URL、タイトル、概要、スキの数を取得して、dictとしてリストに追加する。 contents.append({ 'url': a.get_attribute('href'), 'title': div.find_element_by_css_selector('h3').text, 'description': description, 'like': int( div.find_element_by_css_selector( '.o-noteStatus__item--like .o-noteStatus__label').text), }) return contents
def test_search_fachrul(self, browser: webdriver.Remote): browser.get('https://id.yahoo.com') browser.find_element_by_id('header-search-input').send_keys( 'github Fachrul Choliluddin' + Keys.ENTER) time.sleep(3) results = browser.find_elements_by_css_selector('h3.title') target = random.choice(results) print(target.text) target.click() time.sleep(3) assert 'fachrul' in str(browser.title).lower()
def test_search_fachrul(self, browser: webdriver.Remote): browser.get('https://duckduckgo.com/') browser.find_element_by_id('search_form_input_homepage').send_keys( 'instagram Fachrul Choliluddin' + Keys.ENTER) time.sleep(3) assert 'Fachrul Choliluddin' in browser.title results = browser.find_elements_by_css_selector('h2.result__title') target = random.choice(results) print('hasil', target.text) target.click() time.sleep(5) assert 'fachrul' in str(browser.title).lower()
def test_search_fachrul(self, browser: webdriver.Remote): browser.get('https://google.co.id') browser.find_element_by_name('q').send_keys( 'Fachrul Choliluddin linkedin' + Keys.ENTER) time.sleep(3) assert 'Fachrul Choliluddin' in browser.title results = browser.find_elements_by_css_selector('.r a h3') target = random.choice(results) print('hasil', target.text) target.click() time.sleep(5) assert 'fachrul' in str(browser.title).lower()
def navigate(driver: Remote): """ 目的のページに遷移する。 """ logging.info('Navigating...') driver.get('https://note.mu/') # noteのトップページを開く。 assert 'note' in driver.title # タイトルに'note'が含まれていることを確認する。 # 3回繰り返す。 for _ in range(3): # 待つべき要素の番号(現在の要素数 + 10)を計算する。 # 最初の2要素だけ親要素が異なるので、現在の要素数の計算からは除く。 n = len( driver.find_elements_by_css_selector( '.o-timeline > div > .o-timeline__item')) + 10 # ページの一番下までスクロールする。 driver.execute_script('scroll(0, document.body.scrollHeight)') logging.info('Waiting for contents to be loaded...') # n番目のコンテンツに対応する要素が表示されるまで待つ。nth-of-type()の番号は1始まり。 # タイムアウトは10秒で、10秒待っても表示されない場合は例外が発生する。 WebDriverWait(driver, 10).until( EC.visibility_of_element_located( (By.CSS_SELECTOR, f'.o-timeline__item:nth-of-type({n})')))
def get_elem(driver: webdriver.Remote, by, locator, timeout): found = 0 if by not in ["id", "css", "class", "xpath"]: raise Exception("invalid by locator type passed to {}".format("get_elem")) start_time = int_time() while found == 0: time.sleep(1) if (int_time() - start_time) > timeout: raise TimeoutError("couldn't find element {}:{} in {}s".format(by, locator, timeout)) if by == "id": elements = driver.find_elements_by_id(locator) if by == "css": elements = driver.find_elements_by_css_selector(locator) if by == "class": elements = driver.find_elements_by_class_name(locator) if by == "xpath": elements = driver.find_elements_by_xpath("/html/body/div[2]/div[2]/div/form/input[5]") if elements == None: logger.debug("no elements found, trying again...") continue found = len(elements) if found == 0: logger.debug("no elements found, trying again...") return elements[0]
class Browser: __AWAIT_TIMEOUT = 60 __browser = None __browser_kwargs = {} __config = {} __refs_num = 0 def get_browser(self): return self.__browser def __init__(self, headless=True, config={}, **kwargs): self.__config = config self.__config['SELENIUM_HEADLESS'] = headless self.__browser_kwargs = kwargs if self.__config.get('SELENIUM_URL'): self.__create_browser_session() else: self.__create_browser_instanse() def __del__(self): if self.__browser: self.__browser.quit() logging.debug("%s: Quitted browser at __del__()", self.__config['CELERY_TASK_DEFAULT_QUEUE']) del self.__browser def __create_browser_instanse(self): options = Options() if self.__config.get('SELENIUM_HEADLESS'): options.headless = True if self.__config.get('SELENIUM_BROWSER'): options.add_experimental_option("debuggerAddress", self.__config['SELENIUM_BROWSER']) if self.__config.get('SELENIUM_DRIVER'): self.__browser_kwargs['executable_path'] = self.__config[ 'SELENIUM_DRIVER'] if self.__config.get( 'LOG_LEVEL') and self.__config['LOG_LEVEL'] == logging.DEBUG: if self.__config.get('SELENIUM_LOG_PATH'): self.__browser_kwargs['service_log_path'] = self.__config[ 'SELENIUM_LOG_PATH'] self.__browser_kwargs['service_args'] = ['--verbose'] if not self.__browser_kwargs.get('executable_path'): self.__browser_kwargs['executable_path'] = '/usr/bin/chromedriver' self.__browser = Chrome(options=options, **self.__browser_kwargs) logging.debug("%s: Created browser instance", self.__config['CELERY_TASK_DEFAULT_QUEUE']) def __create_browser_session(self): options = Options() if self.__config.get('SELENIUM_HEADLESS'): options.headless = True self.__browser = Remote(command_executor=self.__config['SELENIUM_URL'], options=options) logging.debug("Connected to remote browser") def __get_by(self, criterium, value): ignored_exceptions = ( NoSuchElementException, StaleElementReferenceException, ) try: return WebDriverWait(self.__browser, self.__AWAIT_TIMEOUT, ignored_exceptions=ignored_exceptions).until( EC.presence_of_element_located( (criterium, value))) except UnexpectedAlertPresentException as ex: raise ex except TimeoutException as ex: raise NoSuchElementException( f"No element with {criterium} {value} was found", ex) def click_by_id(self, element_id): self.__browser.execute_script(f'$("#{element_id}").click()') def doubleclick(self, element): ActionChains(self.__browser).double_click(element).perform() def execute_script(self, script, *args): return self.__browser.execute_script(script, *args) def dismiss_alert(self): try: self.__browser.switch_to_alert().dismiss() except NoAlertPresentException: pass def find_element_by_xpath(self, xpath): return self.__browser.find_element_by_xpath(xpath) def find_elements_by_xpath(self, xpath): return self.__browser.find_elements_by_xpath(xpath) def find_elements_by_css_selector(self, css): return self.__browser.find_elements_by_css_selector(css) def get(self, url): exception = None for attempt in range(3): try: self.__browser.get(url) exception = None break except Exception as ex: self.quit() self.__create_browser_instanse() exception = ex if exception: raise exception def get_alert(self): try: alert = self.__browser.switch_to_alert() text = alert.text alert.dismiss() return text except NoAlertPresentException: return None def get_element_by_class(self, class_name): return self.__get_by(By.CLASS_NAME, class_name) def get_element_by_css(self, css): return self.__get_by(By.CSS_SELECTOR, css) def get_element_by_id(self, id): return self.__get_by(By.ID, id) def get_element_by_name(self, name): return self.__get_by(By.NAME, name) def switch_to_alert(self): return self.__browser.switch_to.alert def wait_for_url(self, url): try: WebDriverWait(self.__browser, 20).until(EC.url_to_be(url)) except UnexpectedAlertPresentException as ex: raise UnexpectedAlertPresentException(ex.alert_text, f"Didn't get URL {url}") except Exception as ex: raise Exception(f"Didn't get URL {url}", ex) def close(self): self.__browser.get('about:blank') def quit(self): if self.__browser: self.__browser.quit() logging.debug("%s: Quitted browser at quit()", self.__config['CELERY_TASK_DEFAULT_QUEUE']) del self.__browser @property def title(self): return self.__browser.title
class AdminSeleniumWebDriverTestCase(LiveServerTestCase): available_apps = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.sites", ] def _get_remote_capabilities(self, specs): platforms = { "s": "Windows 2008", "x": "Windows 2003", "e": "Windows 2012", "l": "Linux", "m": "Mac 10.6", "i": "Mac 10.8", } browsers = { "ff": "firefox", "op": "opera", "ie": "internet explorer", "sa": "safari", "ip": "ipad", "ih": "iphone", "an": "android", "gc": "chrome", } browser = browsers[specs[:2]] if specs[-1] in platforms: platform = platforms.get(specs[-1]) version = specs[2:-1] else: platform = None version = specs[2:] caps = {"browserName": browser, "version": version, "platform": platform, "public": "public"} if "BUILD_NUMBER" in os.environ: caps["build"] = os.environ["BUILD_NUMBER"] elif "TRAVIS_BUILD_NUMBER" in os.environ: caps["build"] = os.environ["TRAVIS_BUILD_NUMBER"] return caps def _get_local_webdriver_class(self, specs): browsers = { "ff": "selenium.webdriver.Firefox", "op": "selenium.webdriver.Opera", "ie": "selenium.webdriver.Ie", "gc": "selenium.webdriver.Chrome", } return import_by_path(browsers[specs[:2]]) def setUp(self): test_method = getattr(self, self._testMethodName) if not hasattr(test_method, "spec"): raise SkipTest("Please make sure your test class is decorated with @browserize") elif not test_method.spec: raise SkipTest("Selenium tests not requested") try: selenium_specs = test_method.spec if os.environ.get("DJANGO_SELENIUM_REMOTE", False): webdriver_class = import_by_path("selenium.webdriver.Remote") else: webdriver_class = self._get_local_webdriver_class(selenium_specs) except Exception as e: raise SkipTest( 'Selenium specifications "%s" not valid or ' "corresponding WebDriver not installed: %s" % (selenium_specs, str(e)) ) from selenium.webdriver import Remote if webdriver_class is Remote: if not (os.environ.get("REMOTE_USER") and os.environ.get("REMOTE_KEY")): raise self.failureException( "Both REMOTE_USER and REMOTE_KEY environment variables are required for remote tests." ) capabilities = self._get_remote_capabilities(selenium_specs) capabilities["name"] = self.id() auth = "%(REMOTE_USER)s:%(REMOTE_KEY)s" % os.environ hub = os.environ.get("REMOTE_HUB", "ondemand.saucelabs.com:80") self.selenium = Remote( command_executor="http://%s@%s/wd/hub" % (auth, hub), desired_capabilities=capabilities ) else: self.selenium = webdriver_class() super(AdminSeleniumWebDriverTestCase, self).setUp() def tearDown(self): if hasattr(self, "selenium"): from selenium.webdriver import Remote if isinstance(self.selenium, Remote): self._report_sauce_pass_fail() self.selenium.quit() super(AdminSeleniumWebDriverTestCase, self).tearDown() def _report_sauce_pass_fail(self): # Sauce Labs has no way of knowing if the test passed or failed, so we # let it know. base64string = base64.encodestring("%s:%s" % (os.environ.get("REMOTE_USER"), os.environ.get("REMOTE_KEY")))[:-1] result = json.dumps({"passed": sys.exc_info() == (None, None, None)}) url = "/rest/v1/%s/jobs/%s" % (os.environ.get("REMOTE_USER"), self.selenium.session_id) connection = httplib.HTTPConnection("saucelabs.com") connection.request("PUT", url, result, headers={"Authorization": "Basic %s" % base64string}) result = connection.getresponse() return result.status == 200 def wait_until(self, callback, timeout=10): """ Helper function that blocks the execution of the tests until the specified callback returns a value that is not falsy. This function can be called, for example, after clicking a link or submitting a form. See the other public methods that call this function for more details. """ from selenium.webdriver.support.wait import WebDriverWait WebDriverWait(self.selenium, timeout).until(callback) def wait_loaded_tag(self, tag_name, timeout=10): """ Helper function that blocks until the element with the given tag name is found on the page. """ self.wait_until(lambda driver: driver.find_element_by_tag_name(tag_name), timeout) def wait_page_loaded(self): """ Block until page has started to load. """ from selenium.common.exceptions import TimeoutException try: # Wait for the next page to be loaded self.wait_loaded_tag("body") except TimeoutException: # IE7 occasionnally returns an error "Internet Explorer cannot # display the webpage" and doesn't load the next page. We just # ignore it. pass def admin_login(self, username, password, login_url="/admin/"): """ Helper function to log into the admin. """ self.selenium.get("%s%s" % (self.live_server_url, login_url)) username_input = self.selenium.find_element_by_name("username") username_input.send_keys(username) password_input = self.selenium.find_element_by_name("password") password_input.send_keys(password) login_text = _("Log in") self.selenium.find_element_by_xpath('//input[@value="%s"]' % login_text).click() self.wait_page_loaded() def get_css_value(self, selector, attribute): """ Helper function that returns the value for the CSS attribute of an DOM element specified by the given selector. Uses the jQuery that ships with Django. """ return self.selenium.execute_script('return django.jQuery("%s").css("%s")' % (selector, attribute)) def get_select_option(self, selector, value): """ Returns the <OPTION> with the value `value` inside the <SELECT> widget identified by the CSS selector `selector`. """ from selenium.common.exceptions import NoSuchElementException options = self.selenium.find_elements_by_css_selector("%s > option" % selector) for option in options: if option.get_attribute("value") == value: return option raise NoSuchElementException('Option "%s" not found in "%s"' % (value, selector)) def assertSelectOptions(self, selector, values): """ Asserts that the <SELECT> widget identified by `selector` has the options with the given `values`. """ options = self.selenium.find_elements_by_css_selector("%s > option" % selector) actual_values = [] for option in options: actual_values.append(option.get_attribute("value")) self.assertEqual(values, actual_values) def has_css_class(self, selector, klass): """ Returns True if the element identified by `selector` has the CSS class `klass`. """ return self.selenium.find_element_by_css_selector(selector).get_attribute("class").find(klass) != -1