Who Is This Course For?
This course is for testers and career switchers who want to learn Python without drowning in theory. Every topic is explained in plain language first — then you see the exact syntax. You will leave knowing not just how to write Python, but why each feature exists and how it directly helps you write better automated tests.
- Installing Python 3 and configuring the PATH so you can run it from anywhere on your computer
- Setting up PyCharm IDE — creating your first project and running a
.pyfile - Understanding compiled vs interpreted — why Python runs without a separate compile step
- What "exit code 0" means — your program finished without errors
- Python's family tree: CPython (standard), Jython, PyPy, Brython — and why CPython is what we use
- A variable is a labelled box —
age = 25puts the number 25 in a box called "age" - Identifier rules: letters, digits, underscore only; cannot start with a digit; case-sensitive
- Python's 35 reserved keywords:
if,else,for,while,def,class,return,pass— you cannot use these as variable names - Constants by convention:
MAX_RETRIES = 3— all caps signals "don't change this"
-
int— whole numbers;float— decimals;complex—3+4j(rarely needed in testing) -
bool—TrueorFalse: the result of every comparison in your tests -
str— text in single, double, or triple quotes: your API responses, usernames, messages -
None— means "nothing" or "not set yet" — common in API responses for missing fields -
type(x)— tells you what kind of data x holds;input()— always returns a string, cast withint()
-
list—[1, 2, 3]: ordered, changeable, allows duplicates — your default go-to for sequences -
tuple—(1, 2, 3): ordered, locked (immutable) — use when data must not change -
set—{1, 2, 3}: no order, no duplicates — perfect for unique test IDs -
frozenset— same as set but locked — used as dictionary keys -
dict—{"name": "Bhanu"}: lookup by label — like a row of test data with named fields -
range—range(1, 10): a lazy sequence of numbers — drives loops without storing all values -
str— text is also a sequence — every character has an index and can be iterated
- Standard maths:
+-*/; integer division://; power:**; remainder:% - Shortcut update:
count += 1instead ofcount = count + 1 - String joining:
"Hello " + name; repeating:"-" * 30(separator lines in reports)
- Compare:
==!=><>=<=— every comparison returnsTrueorFalse - Combine conditions:
and(both must be true),or(at least one),not(flip) - Check existence:
"admin" in roles— one-line membership check on any container - Identity vs equality:
ischecks if two variables point to the exact same object;==checks if values match
-
if condition:— run this block only when the condition is true -
if-else— two paths: one for true, one for false -
if-elif-elif-else— check multiple conditions in order; stop at first match - Nested
if— condition inside a condition, like checking age AND nationality
-
for item in collection:— go through every item;for i in range(n):— repeat n times -
while condition:— keep going until the condition becomes false -
break— exit the loop immediately (found what you needed);continue— skip this one, go to next - Nested loops — a loop inside a loop, used for comparing every pair in two lists or printing pattern grids
-
print(end="")— print without adding a new line, useful for same-row output in nested loops
- Indexing:
items[0]is first,items[-1]is last — negative index counts from the end - Slicing:
items[1:4]gives elements at positions 1, 2, 3 (end is exclusive) - Step slicing:
items[::2]— every other element;items[::-1]— reversed copy - Quick stats:
len(),min(),max(),sum(),sorted()— no loops needed
- Add:
append(x)at end;insert(i, x)at position;extend(list2)merge - Remove:
remove(x)by value;pop(i)by index and returns it;clear()empties list - Organise:
sort()in place;reverse()in place;copy()to avoid changing original - Search:
count(x)— how many times x appears;index(x)— where x first appears
-
[x*2 for x in numbers]— create a transformed list in one line instead of a 4-line loop -
[x for x in numbers if x > 0]— filter and collect in one line - Unpacking:
a, b, *rest = my_list— grab first two items; everything else goes intorest - Tuples: same indexing as lists but immutable — use when you need to guarantee data won't change
- Case change:
upper(),lower(),title()— normalise user input before asserting - Check type:
isalpha(),isalnum(),isnumeric()— validate field content - Search:
startswith("https"),endswith(".json"),find("error"),count("a") - Clean:
strip()removes leading/trailing whitespace — essential for data from files - Split/join:
"a,b,c".split(",")→["a","b","c"];",".join(list)→ back to string - f-strings:
f"Status: {code}"— insert variable values directly into text; the cleanest formatting approach
- Sets automatically remove duplicates — pass a list with repeats to
set()to deduplicate instantly -
add(),remove(),discard()(no error if missing),pop(),clear() - Set maths:
union()(all of both),intersection()(shared only),difference()(in A not B)
- Create:
{"username": "bhanu", "role": "admin"}— each JSON object you parse becomes this - Safe read:
d.get("key")returnsNoneinstead of crashing when key is missing - Loop:
d.keys(),d.values(),d.items()— iterate over what you need - Counting pattern:
d[key] = d.get(key, 0) + 1— count occurrences without a separate counter per item
-
def login(username, password):— define;login("bhanu","pass123")— call - Positional arguments — order determines which value goes where
- Keyword arguments —
login(password="pass", username="bhanu")— order does not matter - Default values —
def greet(name="Guest"):— caller can skip it when default is fine - Variable number of arguments —
*argspacks any number of extras into a tuple
-
return result— send a value back to the caller -
return a, b— send back multiple values as a tuple; unpack withx, y = func() - Recursive function: solves a problem by calling itself with a smaller version — useful for tree/nested structures
- Python stops recursion at ~996 calls to prevent infinite loops — always define a base case that returns without calling itself
- Lambda:
lambda x: x > 0— a tiny throw-away function with no name, used inline -
filter(lambda x: x > 0, numbers)— keep only items where the condition is true -
map(lambda x: x * 1.1, prices)— apply a transformation to every item (e.g. add tax) - Both return lazy objects — wrap with
list()to see the result - When to use list comprehension vs filter/map — comprehensions are more readable for simple cases
-
from functools import reduce;reduce(lambda a,b: a+b, nums)— collapse a list to one value - Use
reducefor: total, product, max of a list, concatenating words - Generator function: uses
yield— produces one value at a time instead of building the whole list in memory - Generator expression:
(x for x in data if x > 0)— same as list comprehension but memory-efficient - Why generators matter in testing: stream through 100,000 test records without loading them all into RAM
- Class = blueprint; Object = a copy made from the blueprint:
obj = MyClass() -
__init__(self, params)— runs automatically the moment you create an object; sets its starting values -
self— every method receives the object itself as first argument so it can access its own data - Instance attribute: belongs to one object; class variable: shared by all objects of that class
- Instance method:
def validate(self):— called on an object; operates on its data -
@classmethod— bound to the class, not an instance; receivesclsinstead ofself -
__str__(self)— controls whatprint(obj)shows; override to display meaningful info instead of a memory address -
type(obj)— which class it came from;id(obj)— its unique memory address
- Public by default — any code can read or change your object's attributes
- Private with
__:self.__balance— only accessible through methods of the same class - Why it matters: a Bank Account's balance should only change via
deposit()andwithdraw(), never directly - Python name mangling:
__balanceis internally renamed to_Account__balance
-
class Child(Parent):— Child gets everything Parent has automatically - Method overriding: Child redefines a method to behave differently — same name, different body
- Multiple inheritance:
class C(A, B):— gets from both parents; Python resolves conflicts left to right (MRO) - Call parent constructor explicitly:
Parent.__init__(self)when child has its own__init__
-
from abc import ABC, abstractmethod -
class Animal(ABC):— abstract class cannot be instantiated directly -
@abstractmethod def make_sound(self): pass— every subclass MUST implement this or Python raises an error - Real-world use: architect defines the required API, developers implement it for each product/platform
-
try:— put the risky code here (database calls, HTTP requests, file reads) -
except ZeroDivisionError:— catch a specific type;except:— catch anything -
finally:— this block ALWAYS runs, even after an exception — perfect for cleanup (close DB, logout, delete test data) - Reading a stack trace: Python prints the chain of function calls from bottom (where it happened) to top (where you started)
- Pattern:
open_connection() → try: do_work() → except: log_error → finally: close_connection()
- Files must be named
test_*.py— Pytest only looks in these files - Functions must start with
test_— anything else is ignored; helpful for helper functions in the same file - Classes must start with
Testwith no__init__method - Run from terminal:
pytest(all tests) orpytest -v(verbose, shows each test name)
-
assert response_code == 200— one line to declare a test passes or fails - Pytest continues to next test after a failure — unlike a plain script that stops at the first problem
-
@pytest.fixture— marks a function as setup/teardown provider, not a test itself -
autouse=True— applies the fixture to every test in scope without naming it as an argument -
yieldinside fixture: code beforeyield= setup (runs first); code after = teardown (always runs) -
scope="function"/"class"/"module"/"session"— controls how often setup runs
-
conftest.py— place shared fixtures here and every test file in that directory can use them automatically -
params=["apple","mango","banana"]in fixture — Pytest runs each test once per value;request.paramgives you the current value - Fixture inside a
BaseTestclass — subclasses inherit it; same pattern as the Java BaseClass you already know
-
pip install allure-pytest; runpytest --alluredir=./results -
allure serve ./results— opens a rich HTML report showing pass/fail, duration, timeline, and test steps - Why Allure matters: stakeholders and managers can read it — it is not just a developer console log
-
import openpyxl— no Excel application needed to read .xlsx files -
wb = openpyxl.load_workbook("testdata.xlsx")— open the file -
sheet = wb["Sheet1"]— navigate to the right tab -
sheet.cell(row, col).value— read any cell by row and column number - Always call
wb.close()when done — good hygiene, prevents file lock issues
-
import pandas as pd;df = pd.read_csv("data.csv")— entire file loaded as a DataFrame - DataFrame = a table with named columns — like a spreadsheet in memory
-
df.to_dict(orient="records")— converts each row into a dictionary; loop through to drive parameterised tests
-
import json;data = json.loads(response_string)— parse a JSON string into a Python dictionary -
json.load(open("data.json"))— parse directly from a file - Type mapping: JSON object →
dict; array →list; true/false →True/False; null →None - After parsing:
data["city"]— access fields exactly like a regular Python dictionary - Why this matters: every API response you test in REST Assured/Requests arrives as JSON — Python instantly turns it into a dict you can assert against
Python Fundamentals Q&A
What is the difference between is and ==? Explain with an example. When does // give a different result than /? What is name mangling and why does Python use it?
OOP Interview Q&A
Explain encapsulation using a Bank Account example. What is Method Resolution Order in multiple inheritance? What makes a class abstract and why would you use one in a test framework?
Functional Programming Q&A
When would you use filter() over a list comprehension? What does yield do and why does it save memory? Show how reduce() finds the maximum value in a list.
Pytest Q&A
What is conftest.py and why is it better than duplicating fixtures? What is the difference between scope="function" and scope="session"? Show a fixture that uses yield for cleanup.