Skip to content

Commit 34048f1

Browse files
committed
update "deisgn_strategies.en.md" to utilize codeblock
1 parent 8c38e8f commit 34048f1

File tree

1 file changed

+27
-264
lines changed

1 file changed

+27
-264
lines changed

website_and_docs/content/documentation/test_practices/design_strategies.en.md

Lines changed: 27 additions & 264 deletions
Original file line numberDiff line numberDiff line change
@@ -449,280 +449,43 @@ An example of `python + pytest + selenium` which implemented "**Action Bot**, **
449449

450450
A `pytest` fixture `chrome_driver`.
451451

452-
```python
453-
import pytest
454-
from selenium import webdriver
455-
from selenium.common import (
456-
ElementNotInteractableException,
457-
NoSuchElementException,
458-
StaleElementReferenceException,
459-
)
460-
from selenium.webdriver import ActionChains
461-
from selenium.webdriver.common.by import By
462-
from selenium.webdriver.remote.webelement import WebElement
463-
from selenium.webdriver.support import expected_conditions as EC
464-
from selenium.webdriver.support.ui import WebDriverWait
465-
466-
467-
@pytest.fixture(scope="function")
468-
def chrome_driver():
469-
with webdriver.Chrome() as driver:
470-
driver.set_window_size(1024, 768)
471-
driver.implicitly_wait(0.5)
472-
yield driver
473-
```
452+
{{< tabpane text=true >}}
453+
{{< tab header="Python" >}}
454+
{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L6-L26" >}}
455+
{{< /tab >}}
456+
{{< /tabpane >}}
457+
474458

475459
"**Action Bot**" implementation.
476460

477-
```python
478-
class ActionBot:
479-
def __init__(self, driver) -> None:
480-
self.driver = driver
481-
self.wait = WebDriverWait(
482-
driver,
483-
timeout=10,
484-
poll_frequency=2,
485-
ignored_exceptions=[
486-
NoSuchElementException,
487-
StaleElementReferenceException,
488-
ElementNotInteractableException,
489-
],
490-
)
491-
492-
def element(self, locator: tuple) -> WebElement:
493-
self.wait.until(lambda driver: driver.find_element(*locator))
494-
return self.driver.find_element(*locator)
495-
496-
def elements(self, locator: tuple) -> list[WebElement]:
497-
return self.driver.find_elements(*locator)
498-
499-
def hover(self, locator: tuple) -> None:
500-
element = self.element(locator)
501-
ActionChains(self.driver).move_to_element(element).perform()
502-
503-
def click(self, locator: tuple) -> None:
504-
element = self.element(locator)
505-
element.click()
506-
507-
def type(self, locator: tuple, value: str) -> None:
508-
element = self.element(locator)
509-
element.clear()
510-
element.send_keys(value)
511-
512-
def text(self, locator: tuple) -> str:
513-
element = self.element(locator)
514-
return element.text
515-
```
461+
{{< tabpane text=true >}}
462+
{{< tab header="Python" >}}
463+
{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L28-L65" >}}
464+
{{< /tab >}}
465+
{{< /tabpane >}}
516466

517-
"**Loadable Component** definition.
518467

519-
```python
520-
class LoadableComponent:
521-
def load(self):
522-
raise NotImplementedError("Subclasses must implement this method")
468+
"**Loadable Component** definition.
523469

524-
def is_loaded(self):
525-
raise NotImplementedError("Subclasses must implement this method")
470+
{{< tabpane text=true >}}
471+
{{< tab header="Python" >}}
472+
{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L67-L80" >}}
473+
{{< /tab >}}
474+
{{< /tabpane >}}
526475

527-
def get(self):
528-
if not self.is_loaded():
529-
self.load()
530-
if not self.is_loaded():
531-
raise Exception("Page not loaded properly.")
532-
return self
533-
```
534476

535477
"**Loadable Component** and **Page Object**" implementation.
536478

537-
```python
538-
class TodoPage(LoadableComponent):
539-
url = "https://todomvc.com/examples/react/dist/"
540-
541-
new_todo_by = (By.CSS_SELECTOR, "input.new-todo")
542-
count_todo_left_by = (By.CSS_SELECTOR, "span.todo-count")
543-
todo_items_by = (By.CSS_SELECTOR, "ul.todo-list>li")
544-
545-
view_all_by = (By.LINK_TEXT, "All")
546-
view_active_by = (By.LINK_TEXT, "Active")
547-
view_completed_by = (By.LINK_TEXT, "Completed")
548-
549-
toggle_all_by = (By.CSS_SELECTOR, "input.toggle-all")
550-
clear_completed_by = (By.CSS_SELECTOR, "button.clear-completed")
551-
552-
@staticmethod
553-
def build_todo_by(s: str) -> tuple:
554-
p = f"//li[.//label[contains(text(), '{s}')]]"
555-
return By.XPATH, p
556-
557-
@staticmethod
558-
def build_todo_item_label_by(s: str) -> tuple:
559-
p = f"//label[contains(text(), '{s}')]"
560-
return By.XPATH, p
561-
562-
@staticmethod
563-
def build_todo_item_toggle_by(s: str) -> tuple:
564-
by, using = TodoPage.build_todo_item_label_by(s)
565-
p = f"{using}/../input[@class='toggle']"
566-
return by, p
567-
568-
@staticmethod
569-
def build_todo_item_delete_by(s: str) -> tuple:
570-
by, using = TodoPage.build_todo_item_label_by(s)
571-
p = f"{using}/../button[@class='destroy']"
572-
return by, p
573-
574-
def build_count_todo_left(self, count: int) -> str:
575-
if count == 1:
576-
return "1 item left!"
577-
else:
578-
return f"{count} items left!"
579-
580-
def __init__(self, driver):
581-
self.driver = driver
582-
self.bot = ActionBot(driver)
583-
584-
def load(self):
585-
self.driver.get(self.url)
586-
587-
def is_loaded(self):
588-
try:
589-
WebDriverWait(self.driver, 10).until(
590-
EC.visibility_of_element_located(self.new_todo_by)
591-
)
592-
return True
593-
except:
594-
return False
595-
596-
# business domain below
597-
def count_todo_items_left(self) -> str:
598-
return self.bot.text(self.count_todo_left_by)
599-
600-
def todo_count(self) -> int:
601-
return len(self.bot.elements(self.todo_items_by))
602-
603-
def new_todo(self, s: str):
604-
self.bot.type(self.new_todo_by, s + "\n")
605-
606-
def toggle_todo(self, s: str):
607-
self.bot.click(self.build_todo_item_toggle_by(s))
608-
609-
def hover_todo(self, s: str) -> None:
610-
self.bot.hover(self.build_todo_by(s))
611-
612-
def delete_todo(self, s: str):
613-
self.hover_todo(s)
614-
self.bot.click(self.build_todo_item_delete_by(s))
615-
616-
def clear_completed_todo(self):
617-
self.bot.click(self.clear_completed_by)
618-
619-
def toggle_all_todo(self):
620-
self.bot.click(self.toggle_all_by)
621-
622-
def view_all_todo(self):
623-
self.bot.click(self.view_all_by)
624-
625-
def view_active_todo(self):
626-
self.bot.click(self.view_active_by)
627-
628-
def view_completed_todo(self):
629-
self.bot.click(self.view_completed_by)
630-
```
479+
{{< tabpane text=true >}}
480+
{{< tab header="Python" >}}
481+
{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L82-L172" >}}
482+
{{< /tab >}}
483+
{{< /tabpane >}}
631484

632485
Test cases implementation with `pytest`.
633486

634-
```python
635-
@pytest.fixture
636-
def page(chrome_driver) -> TodoPage:
637-
driver = chrome_driver
638-
return TodoPage(driver).get()
639-
640-
641-
class TestTodoPage:
642-
def test_new_todo(self, page: TodoPage):
643-
assert page.todo_count() == 0
644-
page.new_todo("aaa")
645-
assert page.count_todo_items_left() == page.build_count_todo_left(1)
646-
647-
def test_todo_toggle(self, page: TodoPage):
648-
s = "aaa"
649-
page.new_todo(s)
650-
assert page.count_todo_items_left() == page.build_count_todo_left(1)
651-
652-
page.toggle_todo(s)
653-
assert page.count_todo_items_left() == page.build_count_todo_left(0)
654-
655-
page.toggle_todo(s)
656-
assert page.count_todo_items_left() == page.build_count_todo_left(1)
657-
658-
def test_todo_delete(self, page: TodoPage):
659-
s1 = "aaa"
660-
s2 = "bbb"
661-
page.new_todo(s1)
662-
page.new_todo(s2)
663-
assert page.count_todo_items_left() == page.build_count_todo_left(2)
664-
665-
page.delete_todo(s1)
666-
assert page.count_todo_items_left() == page.build_count_todo_left(1)
667-
668-
page.delete_todo(s2)
669-
assert page.todo_count() == 0
670-
671-
def test_new_100_todo(self, page: TodoPage):
672-
for i in range(100):
673-
s = f"ToDo{i}"
674-
page.new_todo(s)
675-
assert page.count_todo_items_left() == page.build_count_todo_left(100)
676-
677-
def test_toggle_all_todo(self, page: TodoPage):
678-
for i in range(10):
679-
s = f"ToDo{i}"
680-
page.new_todo(s)
681-
assert page.count_todo_items_left() == page.build_count_todo_left(10)
682-
assert page.todo_count() == 10
683-
684-
page.toggle_all_todo()
685-
assert page.count_todo_items_left() == page.build_count_todo_left(0)
686-
assert page.todo_count() == 10
687-
688-
page.toggle_all_todo()
689-
assert page.count_todo_items_left() == page.build_count_todo_left(10)
690-
assert page.todo_count() == 10
691-
692-
def test_clear_completed_todo(self, page: TodoPage):
693-
for i in range(10):
694-
s = f"ToDo{i}"
695-
page.new_todo(s)
696-
assert page.count_todo_items_left() == page.build_count_todo_left(10)
697-
assert page.todo_count() == 10
698-
699-
for i in range(5):
700-
s = f"ToDo{i}"
701-
page.toggle_todo(s)
702-
assert page.count_todo_items_left() == page.build_count_todo_left(5)
703-
assert page.todo_count() == 10
704-
705-
page.clear_completed_todo()
706-
assert page.count_todo_items_left() == page.build_count_todo_left(5)
707-
assert page.todo_count() == 5
708-
709-
def test_view_todo(self, page: TodoPage):
710-
for i in range(10):
711-
s = f"ToDo{i}"
712-
page.new_todo(s)
713-
for i in range(4):
714-
s = f"ToDo{i}"
715-
page.toggle_todo(s)
716-
717-
page.view_all_todo()
718-
assert page.count_todo_items_left() == page.build_count_todo_left(6)
719-
assert page.todo_count() == 10
720-
721-
page.view_active_todo()
722-
assert page.count_todo_items_left() == page.build_count_todo_left(6)
723-
assert page.todo_count() == 6
724-
725-
page.view_completed_todo()
726-
assert page.count_todo_items_left() == page.build_count_todo_left(6)
727-
assert page.todo_count() == 4
728-
```
487+
{{< tabpane text=true >}}
488+
{{< tab header="Python" >}}
489+
{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L174-" >}}
490+
{{< /tab >}}
491+
{{< /tabpane >}}

0 commit comments

Comments
 (0)