OOP Essentials — Classes, Inheritance, Magic Methods, Decorators
Real SDET code lives in classes — page objects, API clients, base test cases. Here are the essentials you'll actually use, with no heavy theory.
The idea, in one line
A class is a blueprint. From it you make objects that carry their own data and their own actions. Master four small pieces and you can read almost any test framework.
The four pieces
- Class +
__init__:__init__(self, ...)runs when you create an object and stores its data onself—selfis the object itself. Methods are just functions whose first parameter isself, so they can read and change that object's data. - Inheritance: a child class reuses a parent.
class ApiTest(BaseTest)gets everythingBaseTesthas, andsuper().__init__(...)runs the parent's setup before the child adds its own. This is how aBasePagehands every page object a shared driver. - Magic methods: dunder names like
__init__,__repr__,__eq__hook into Python's syntax. Define__repr__and your object prints usefully in a failed assert; define__eq__and==compares by value. - Decorator: wraps a function to add behaviour — timing, logging, retries — without touching its body.
@wrapsfromfunctoolscopies the original's name and docstring so debuggers and test runners still see the real function.
See it work
▸ try it
import functools
# Decorator that retries a flaky step
def retry(times):
def outer(fn):
@functools.wraps(fn) # keep fn's real name/docstring
def inner(*args, **kwargs):
for attempt in range(times):
try:
return fn(*args, **kwargs)
except AssertionError:
if attempt == times - 1:
raise
return inner
return outer
class BasePage:
def __init__(self, url):
self.url = url
def __repr__(self): # useful in a failed assert
return f"{type(self).__name__}({self.url!r})"
class LoginPage(BasePage):
def __init__(self, url, user):
super().__init__(url) # run parent setup
self.user = user
@retry(times=3)
def submit(self):
assert self.user, "no user set"
return "ok"
print(LoginPage("/login", "amy")) # LoginPage('/login')Read it top to bottom: BasePage holds a url and prints itself nicely, LoginPage reuses that setup with super().__init__ and adds a user, and @retry wraps submit so a flaky assert gets a few more tries before it fails.
Advanced — why each piece earns its place
- Inheritance keeps shared setup in one place, so every page object gets the same driver and helpers without copy-paste.
__repr__turns a cryptic failing assert into a readable one — you see the object, not a memory address.- Decorators add retries or timing around a method without editing the method, and
@wrapskeeps the original name so your test report still points at the real function.
Grounded in the official Python docs (classes) and functools
All lessons in Logic Building Bootcamp
- Pattern 1 — Counting how often things appear
- Pattern 2 — Two Pointers
- Pattern 3 — Sliding Window
- Pattern 4 — Index Math & Matrix Walks
- OOP Essentials — Classes, Inheritance, Magic Methods, Decorators