@@ -441,281 +441,43 @@ public class ActionBot {
441441
442442A ` pytest ` fixture ` chrome_driver ` .
443443
444- ``` python
445- import pytest
446- from selenium import webdriver
447- from selenium.common import (
448- ElementNotInteractableException,
449- NoSuchElementException,
450- StaleElementReferenceException,
451- )
452- from selenium.webdriver import ActionChains
453- from selenium.webdriver.common.by import By
454- from selenium.webdriver.remote.webelement import WebElement
455- from selenium.webdriver.support import expected_conditions as EC
456- from selenium.webdriver.support.ui import WebDriverWait
457-
458-
459- @pytest.fixture (scope = " function" )
460- def chrome_driver ():
461- with webdriver.Chrome() as driver:
462- driver.set_window_size(1024 , 768 )
463- driver.implicitly_wait(0.5 )
464- yield driver
465- ```
444+ {{< tabpane text=true >}}
445+ {{< tab header="Python" >}}
446+ {{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L6-L26" >}}
447+ {{< /tab >}}
448+ {{< /tabpane >}}
449+
466450
467451"** Action Bot** " implementation.
468452
469- ``` python
470- class ActionBot :
471- def __init__ (self , driver ) -> None :
472- self .driver = driver
473- self .wait = WebDriverWait(
474- driver,
475- timeout = 10 ,
476- poll_frequency = 2 ,
477- ignored_exceptions = [
478- NoSuchElementException,
479- StaleElementReferenceException,
480- ElementNotInteractableException,
481- ],
482- )
483-
484- def element (self , locator : tuple ) -> WebElement:
485- self .wait.until(lambda driver : driver.find_element(* locator))
486- return self .driver.find_element(* locator)
487-
488- def elements (self , locator : tuple ) -> list[WebElement]:
489- return self .driver.find_elements(* locator)
490-
491- def hover (self , locator : tuple ) -> None :
492- element = self .element(locator)
493- ActionChains(self .driver).move_to_element(element).perform()
494-
495- def click (self , locator : tuple ) -> None :
496- element = self .element(locator)
497- element.click()
498-
499- def type (self , locator : tuple , value : str ) -> None :
500- element = self .element(locator)
501- element.clear()
502- element.send_keys(value)
503-
504- def text (self , locator : tuple ) -> str :
505- element = self .element(locator)
506- return element.text
507- ```
453+ {{< tabpane text=true >}}
454+ {{< tab header="Python" >}}
455+ {{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L28-L65" >}}
456+ {{< /tab >}}
457+ {{< /tabpane >}}
508458
509- "** Loadable Component** definition.
510459
511- ``` python
512- class LoadableComponent :
513- def load (self ):
514- raise NotImplementedError (" Subclasses must implement this method" )
460+ "** Loadable Component** definition.
515461
516- def is_loaded (self ):
517- raise NotImplementedError (" Subclasses must implement this method" )
462+ {{< tabpane text=true >}}
463+ {{< tab header="Python" >}}
464+ {{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L67-L80" >}}
465+ {{< /tab >}}
466+ {{< /tabpane >}}
518467
519- def get (self ):
520- if not self .is_loaded():
521- self .load()
522- if not self .is_loaded():
523- raise Exception (" Page not loaded properly." )
524- return self
525- ```
526468
527469"** Loadable Component** and ** Page Object** " implementation.
528470
529- ``` python
530- class TodoPage (LoadableComponent ):
531- url = " https://todomvc.com/examples/react/dist/"
532-
533- new_todo_by = (By.CSS_SELECTOR , " input.new-todo" )
534- count_todo_left_by = (By.CSS_SELECTOR , " span.todo-count" )
535- todo_items_by = (By.CSS_SELECTOR , " ul.todo-list>li" )
536-
537- view_all_by = (By.LINK_TEXT , " All" )
538- view_active_by = (By.LINK_TEXT , " Active" )
539- view_completed_by = (By.LINK_TEXT , " Completed" )
540-
541- toggle_all_by = (By.CSS_SELECTOR , " input.toggle-all" )
542- clear_completed_by = (By.CSS_SELECTOR , " button.clear-completed" )
543-
544- @ staticmethod
545- def build_todo_by (s : str ) -> tuple :
546- p = f " //li[.//label[contains(text(), ' { s} ')]] "
547- return By.XPATH , p
548-
549- @ staticmethod
550- def build_todo_item_label_by (s : str ) -> tuple :
551- p = f " //label[contains(text(), ' { s} ')] "
552- return By.XPATH , p
553-
554- @ staticmethod
555- def build_todo_item_toggle_by (s : str ) -> tuple :
556- by, using = TodoPage.build_todo_item_label_by(s)
557- p = f " { using} /../input[@class='toggle'] "
558- return by, p
559-
560- @ staticmethod
561- def build_todo_item_delete_by (s : str ) -> tuple :
562- by, using = TodoPage.build_todo_item_label_by(s)
563- p = f " { using} /../button[@class='destroy'] "
564- return by, p
565-
566- def build_count_todo_left (self , count : int ) -> str :
567- if count == 1 :
568- return " 1 item left!"
569- else :
570- return f " { count} items left! "
571-
572- def __init__ (self , driver ):
573- self .driver = driver
574- self .bot = ActionBot(driver)
575-
576- def load (self ):
577- self .driver.get(self .url)
578-
579- def is_loaded (self ):
580- try :
581- WebDriverWait(self .driver, 10 ).until(
582- EC .visibility_of_element_located(self .new_todo_by)
583- )
584- return True
585- except :
586- return False
587-
588- # business domain below
589- def count_todo_items_left (self ) -> str :
590- return self .bot.text(self .count_todo_left_by)
591-
592- def todo_count (self ) -> int :
593- return len (self .bot.elements(self .todo_items_by))
594-
595- def new_todo (self , s : str ):
596- self .bot.type(self .new_todo_by, s + " \n " )
597-
598- def toggle_todo (self , s : str ):
599- self .bot.click(self .build_todo_item_toggle_by(s))
600-
601- def hover_todo (self , s : str ) -> None :
602- self .bot.hover(self .build_todo_by(s))
603-
604- def delete_todo (self , s : str ):
605- self .hover_todo(s)
606- self .bot.click(self .build_todo_item_delete_by(s))
607-
608- def clear_completed_todo (self ):
609- self .bot.click(self .clear_completed_by)
610-
611- def toggle_all_todo (self ):
612- self .bot.click(self .toggle_all_by)
613-
614- def view_all_todo (self ):
615- self .bot.click(self .view_all_by)
616-
617- def view_active_todo (self ):
618- self .bot.click(self .view_active_by)
619-
620- def view_completed_todo (self ):
621- self .bot.click(self .view_completed_by)
622- ```
471+ {{< tabpane text=true >}}
472+ {{< tab header="Python" >}}
473+ {{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L82-L172" >}}
474+ {{< /tab >}}
475+ {{< /tabpane >}}
623476
624477Test cases implementation with ` pytest ` .
625478
626- ``` python
627- @pytest.fixture
628- def page (chrome_driver ) -> TodoPage:
629- driver = chrome_driver
630- return TodoPage(driver).get()
631-
632-
633- class TestTodoPage :
634- def test_new_todo (self , page : TodoPage):
635- assert page.todo_count() == 0
636- page.new_todo(" aaa" )
637- assert page.count_todo_items_left() == page.build_count_todo_left(1 )
638-
639- def test_todo_toggle (self , page : TodoPage):
640- s = " aaa"
641- page.new_todo(s)
642- assert page.count_todo_items_left() == page.build_count_todo_left(1 )
643-
644- page.toggle_todo(s)
645- assert page.count_todo_items_left() == page.build_count_todo_left(0 )
646-
647- page.toggle_todo(s)
648- assert page.count_todo_items_left() == page.build_count_todo_left(1 )
649-
650- def test_todo_delete (self , page : TodoPage):
651- s1 = " aaa"
652- s2 = " bbb"
653- page.new_todo(s1)
654- page.new_todo(s2)
655- assert page.count_todo_items_left() == page.build_count_todo_left(2 )
656-
657- page.delete_todo(s1)
658- assert page.count_todo_items_left() == page.build_count_todo_left(1 )
659-
660- page.delete_todo(s2)
661- assert page.todo_count() == 0
662-
663- def test_new_100_todo (self , page : TodoPage):
664- for i in range (100 ):
665- s = f " ToDo { i} "
666- page.new_todo(s)
667- assert page.count_todo_items_left() == page.build_count_todo_left(100 )
668-
669- def test_toggle_all_todo (self , page : TodoPage):
670- for i in range (10 ):
671- s = f " ToDo { i} "
672- page.new_todo(s)
673- assert page.count_todo_items_left() == page.build_count_todo_left(10 )
674- assert page.todo_count() == 10
675-
676- page.toggle_all_todo()
677- assert page.count_todo_items_left() == page.build_count_todo_left(0 )
678- assert page.todo_count() == 10
679-
680- page.toggle_all_todo()
681- assert page.count_todo_items_left() == page.build_count_todo_left(10 )
682- assert page.todo_count() == 10
683-
684- def test_clear_completed_todo (self , page : TodoPage):
685- for i in range (10 ):
686- s = f " ToDo { i} "
687- page.new_todo(s)
688- assert page.count_todo_items_left() == page.build_count_todo_left(10 )
689- assert page.todo_count() == 10
690-
691- for i in range (5 ):
692- s = f " ToDo { i} "
693- page.toggle_todo(s)
694- assert page.count_todo_items_left() == page.build_count_todo_left(5 )
695- assert page.todo_count() == 10
696-
697- page.clear_completed_todo()
698- assert page.count_todo_items_left() == page.build_count_todo_left(5 )
699- assert page.todo_count() == 5
700-
701- def test_view_todo (self , page : TodoPage):
702- for i in range (10 ):
703- s = f " ToDo { i} "
704- page.new_todo(s)
705- for i in range (4 ):
706- s = f " ToDo { i} "
707- page.toggle_todo(s)
708-
709- page.view_all_todo()
710- assert page.count_todo_items_left() == page.build_count_todo_left(6 )
711- assert page.todo_count() == 10
712-
713- page.view_active_todo()
714- assert page.count_todo_items_left() == page.build_count_todo_left(6 )
715- assert page.todo_count() == 6
716-
717- page.view_completed_todo()
718- assert page.count_todo_items_left() == page.build_count_todo_left(6 )
719- assert page.todo_count() == 4
720- ```
721-
479+ {{< tabpane text=true >}}
480+ {{< tab header="Python" >}}
481+ {{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L174-" >}}
482+ {{< /tab >}}
483+ {{< /tabpane >}}
0 commit comments