Koding Tree offers comprehensive training in Advanced Selenium, API Manual Testing, Rest Assured, DevOps, and Java, covering everything from core fundamentals to advanced automation and system-level concepts
💡 Why this matters: Most testers use only basic TestNG. Mastering @DataProvider, @Factory, and dependsOnMethods lets you run smarter, data-driven, and highly controlled test suites — skills that immediately impress in interviews.
@BeforeSuite, @BeforeTest, @BeforeClass, @BeforeMethod, @AfterMethod, @AfterClass, @AfterSuiteinvocationCount – running a test method multiple times; constraints and valid use casespriority – default value 0; negative values allowed; alphabetical tie-breakingdependsOnMethods – precedence over priority when both are setenabled=false vs alwaysRun=true – controlling test skipping within groupstestng.xml files into one run using <suite-files>Object[] – single-parameter dataset; Object[][] – multi-row multi-column datasetIterator<Object[]> – lazy loading for large datasets without loading everything into memoryMap is not a valid @DataProvider return typeAssert vs SoftAssert – fail-fast vs collect-all-failures strategy@Test(groups) – smoke, regression, sanity; running specific groups from testng.xml@Parameters – passing values from testng.xml into test methods at runtime@Factory – dynamically generating multiple test class instances from a single classTestNG and XmlSuite classes – no XML needed💡 Why this matters: Dependency Injection is how enterprise frameworks avoid duplicating browser setup across dozens of test classes. Understanding java.lang.reflect makes you stand out in senior-level framework design interviews.
WebDriver into test classes via constructor or method parametersjava.lang.Class, java.lang.reflect.Method – inspecting and invoking methods at runtimeWebDriver – when to use each approach in real projects💡 Why this matters: Flaky tests cost teams hours of manual re-runs. Implementing IRetryAnalyzer and ITestListener at the framework level means your suite handles failures automatically — a hallmark of a production-ready framework.
IRetryAnalyzer – implementing retry(ITestResult) to auto re-run failed tests up to a configurable limitITestListener – hooking into onTestFailure(), onTestStart(), onTestSuccess() lifecycle eventsITestResult + TakesScreenshot + FileUtils.copyFile()ExtentReports via Base64 encodingReporter.log() – adding custom step messages visible in the TestNG HTML report@Listeners annotation or the <listeners> block in testng.xml💡 Why this matters: Design patterns are asked in virtually every senior QA interview. Learning to implement and explain them with real Selenium examples puts you ahead of most candidates.
WebDriver instance for the entire test runDriverFactory class – returning ChromeDriver, FirefoxDriver, or EdgeDriver based on input parameterif-else logic from individual test classesEventFiringWebDriver + implementing WebDriverEventListenerEventFiringDecorator wrapping WebDriver + WebDriverListener interfaceclick(), navigate().to(), and exception automatically through the listenerextends AbstractWebDriverEventListener vs implements WebDriverListener💡 Why this matters: Standard POM is just the beginning. Advanced annotations like @FindAll, @FindBys, and @CacheLookup make your page classes faster and more expressive — and interviewers notice the difference.
@FindBy – declaring WebElement and List<WebElement> fields, initialized via PageFactory.initElements(driver, this)@FindAll – locating elements matching any of multiple locators (OR logic)@FindBys – locating elements matching all of multiple locators (AND / parent-child chaining)@CacheLookup – caching the element reference after the first DOM lookup to improve performance@CacheLookup helps vs. when it breaks – dynamic elements, page refresh, AJAX updates@FindAll vs @FindBys – logic difference and when to use each in real tests💡 Why this matters: Knowing three different screenshot approaches — and when each is appropriate — shows depth of knowledge. Most testers only know one method, and interviewers notice.
TakesScreenshot – casting WebDriver and calling getScreenshotAs(OutputType.FILE) for full-page captureFileUtils.copyFile() using timestamped filenames to avoid overwritingWebElement.getScreenshotAs() – capturing just a specific element on the page (Selenium 4)AShot library – full-page screenshots including content below the visible foldRobot class (java.awt.Robot) – OS-level desktop screenshot using createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()))ITestListener.onTestFailure(ITestResult) – no test-level code needed💡 Why this matters: Some elements simply cannot be handled by standard Selenium — hidden inputs, custom widgets, OS-level dialogs. JavascriptExecutor and Robot are what professionals reach for when Selenium hits a wall.
WebDriver to JavascriptExecutor and calling executeScript(String, Object...)window.scrollBy(0, 500); scrolling to element: arguments[0].scrollIntoView()WebElement.click() cannot reach: arguments[0].click()arguments[0].value='text' for blocked input fieldsreturn arguments[0].value / return arguments[0].textContentRobot.mouseMove(x, y), mousePress(InputEvent.BUTTON1_DOWN_MASK), mouseRelease()Robot.keyPress(KeyEvent.VK_ENTER) – keyboard simulation at OS levelStringSelection and Toolkit.getDefaultToolkit().getSystemClipboard() for clipboard operations💡 Why this matters: Professional testers don’t just run tests — they produce shareable evidence. Rich HTML reports and structured log files let your team and stakeholders see exactly what was tested, what passed, and why something failed — with zero manual effort.
ExtentSparkReporter and ExtentReports instance in a base class or listenerExtentTest nodes per test and logging pass(), fail(), skip() with messagesITestListener for automatic lifecycle-driven reportingextent.flush()log4j2.xml / log4j.properties – configuring ConsoleAppender, FileAppender, and log patternsLogManager.getLogger(ClassName.class) – logging at DEBUG, INFO, WARN, ERROR levelsReporter.log() – embedding step-level messages directly into the TestNG HTML reportReporter.getOutput(ITestResult) – reading Reporter messages to attach to ExtentReportWhy this matters:
Real projects store test data in many different formats. Knowing how to read Excel, config files, CSVs, JSON, and databases makes your framework flexible and environment-agnostic — a major differentiator in job interviews.
.xlsx filesMap<String, String> for use in @DataProviderjava.util.Properties — loading key-value config (base URL, credentials) from .properties filesJSONObject / JSONArray or REST Assured’s JsonPathjava.sql.DriverManager.getConnection(url, user, pass)Statement, PreparedStatement, ResultSet — querying DB and comparing values to UI outputWhy this matters:
Jenkins and other CI tools trigger test runs from the command line. If you can only run tests inside an IDE, you cannot work in a real CI/CD pipeline. This module makes your framework pipeline-ready.
mvn test from the terminal — no IDE open, no manual steps-D system properties:mvn test -Dbrowser=chrome -Denv=stagingSystem.getProperty("browser") inside test code and inside testng.xml using ${browser}maven-surefire-plugin <suiteXmlFile> configmvn -Dtest=LoginTest#verifyLogin testpom.xml → testng.xml → @Parameters → test methodWhy this matters: Parallel execution across multiple browsers and machines is how enterprise teams cut test times from hours to minutes. Selenium Grid and cloud platforms are standard tools at any mature QA organization.
java -jar selenium-server.jar standaloneRemoteWebDriver using Hub URL and ChromeOptions / FirefoxOptionstestng.xml using parallel="tests" and thread-countThreadLocal<WebDriver> to avoid cross-thread interferenceRemoteWebDriver with SauceLabs remote Hub URL and access credentialsMutableCapabilities / sauce:optionsWhy this matters: Docker eliminates the “it works on my machine” problem for good. Running Selenium inside Docker containers is now standard practice at companies that run tests in CI pipelines — and it’s a skill most testers don’t have.
docker pull, docker run, docker psselenium/standalone-chrome, selenium/standalone-firefoxRemoteWebDriver to a containerized browser on http://localhost:44445900)docker stop / docker rm — cleaning up environments after test runsWhy this matters: CI/CD integration is the difference between a framework that runs when someone remembers to trigger it, and one that runs automatically on every code change. Jenkins is still the most widely used CI tool in Java test projects.
mvn testString Parameter and Choice Parameter for browser, env, suite-D${browser} in the goals fieldExtentReports HTML inside Jenkins after each runWhy this matters: A Keyword Driven Framework separates test logic from test data – so QA analysts without coding skills can write test cases in Excel and the framework executes them automatically. This is a sign of a senior framework developer.
clickElement(), typeText(), verifyText(), navigateTo()
Why this matters: A working project on a real application is the difference between a resume and a portfolio. You leave this module with something you can demo, explain end-to-end, and be proud of in any senior QA interview.
@FindBy, ExtentReports, Log4j, Excel data, Jenkins CI/CDDesign Patterns
Explain Singleton, Factory, Decorator with real code examples from your own project
Framework Walkthrough
Walk through your package structure, layer responsibilities, and why each design decision was made
CI/CD Pipeline
Describe the full chain: Jenkins → pom.xml → testng.xml → @Parameters → test method
Parallel Execution
Explain ThreadLocal<WebDriver> and how you prevented driver conflicts across parallel threads
Data Strategies
Compare Excel, JSON, Properties, MySQL — and justify where you used each in the project
Docker & Grid
Describe how you used Docker containers as browser nodes and ran tests without installing browsers locally
Why This Module Matters: Before you can test an API, you need to understand what it is and why it exists. This foundation shapes every decision you make as a tester — from what to test, to how to document bugs, to how you explain your work in interviews.
Why This Module Matters: Every single API test you write is based on an HTTP method. Knowing which method to use and what it means is the difference between writing meaningful tests and just clicking Send and hoping for the best.
Why This Module Matters: Status codes are the first thing you check in every test result. A tester who can read a three-digit code and instantly know whether the problem is in the request, the server, or the data is worth far more than one who just checks “did I get a response?”
Why This Module Matters: A complete test validates more than just the response body. Headers, status lines, response time, and parameter types all matter — and knowing every part of a request and response means you catch bugs that less thorough testers miss entirely.
https://api.example.com/v1/users/42/users/{id} — identifies a specific record? for filtering or searching: /products?category=books&limit=10Content-Type: application/json, Authorization: Bearer <token>HTTP/1.1 201 CreatedContent-Type, Cache-Control, X-Request-Id
Why This Module Matters: Almost every modern API sends and receives JSON. If you can’t read and write JSON confidently, you can’t write meaningful request bodies or validate response data accurately. This module is the difference between surface-level testing and deep, reliable testing.
{ "id": 1, "name": "Bhanu", "active": true }["admin", "viewer", "editor"], array of objects:[ { ... }, { ... } ]true / false), null, nested Object, ArrayWhy This Module Matters: Postman is the standard tool for API testing in the industry. Getting comfortable with its interface from day one means you spend your time testing — not fighting the tool. Most QA job descriptions now list Postman as a required skill.
Why This Module Matters: No professional tester hardcodes URLs and tokens into every request. Collections keep your work organised and shareable; environments let the same test run against Dev, Staging, or Production with a single switch; variables make your tests dynamic and reusable.
{{base_url}}, {{token}}{{variable_name}} in URL, header value, or bodypm.environment.set("userId", pm.response.json().id)Why This Module Matters: Most real-world APIs are secured. If you can’t handle authentication in Postman, you can’t test 80% of a real application. Understanding auth also helps you write better security-related negative test cases — which is something every interviewer asks about.
x-api-key: abc123 or as a query parameterAuthorization: Bearer <jwt_token>{{access_token}} — never hardcode tokens in requestspm.environment.set("token", ...)Why This Module Matters: A tester who only checks the happy path misses half the bugs. APIs fail in predictable ways — bad inputs, missing auth, wrong permissions, nonexistent resources. Testing these “expected failure” scenarios is what makes a QA engineer genuinely valuable to a team.
Why This Module Matters: Manual checking — reading the response and deciding if it’s right — doesn’t scale. Test scripts run automatically after every request and give you a pass/fail result instantly. This is what separates a manual tester from a semi-automated API tester, and it’s a skill employers specifically look for.
pm.test("description", function () { ... }) — structure of every Postman test casepm.response.to.have.status(201) — assert the exact status code returnedpm.response.to.have.header("Content-Type") — assert a specific header is presentpm.response.responseTime < 2000 — assert response is under 2 secondsconst json = pm.response.json() — parse response body as a JavaScript objectpm.expect(json.name).to.eql("Bhanu") — assert exact field valuepm.expect(json).to.have.property("id") — assert a key exists in the responsepm.expect(json.id).to.be.a("number") — assert correct data typepm.expect(json.items).to.be.an("array").that.is.not.empty — assert non-empty array.to.include, .to.not.be.null, .to.be.true, .to.be.above(0)Why This Module Matters: Real test scenarios require setup — unique data, fresh tokens, IDs from previous responses. Pre-request scripts automate this setup so your test suite is self-sufficient and repeatable. Without this skill, you end up manually copying values between requests, which defeats the purpose of automation.
pm.environment.set("email", "user" + Date.now() + "@test.com")id → store as {{userId}} → use in GET /users/{{userId}}Why This Module Matters: Running one request at a time isn’t testing — it’s clicking. Collection Runner lets you run your entire test suite in one go and see a complete pass/fail summary. Pairing it with a CSV data file means you can test 50 different inputs without writing 50 separate requests.
{{column_name}} in URL, body, and headers — same request runs with different data each timeWhy This Module Matters: Knowing Postman as a tool isn’t enough. Having a test strategy is a professional skill. Companies hire testers who can look at API documentation, build a complete test plan, organize their work, and plug it into a daily pipeline — not just testers who know how to click Send.
newman run collection.json -e environment.jsonGET vs POST — GET retrieves with no body; POST creates with a body; GET is idempotent (safe to repeat), POST is not
401 vs 403 vs 404 —
PUT vs PATCH — PUT replaces the whole resource; PATCH updates only specified fields
What do you validate? — Status code, response body fields and types, required keys present, response time, content type header
Bearer Token Flow — POST /login → receive token → store → use in header:Authorization: Bearer {{token}}
Data-driven testing — Upload CSV to Collection Runner; each row becomes one test iteration; {{column}} variables pull in each row’s data automatically
try block – code that may throw an exceptioncatch (ExceptionType e) – handling a specific exception typecatch blocks – handling different exception types separatelyfinally block – always executes; used for resource cleanup (closing files, connections)throw keyword – manually throwing an exception from your codethrows keyword – declaring that a method may throw a checked exceptionNullPointerExceptionArrayIndexOutOfBoundsExceptionNumberFormatExceptionArithmeticExceptionArrayList – dynamic array; fast random access; allows duplicates; maintains insertion orderLinkedList – doubly-linked list; fast add/remove at ends; slower random accessadd(), get(int), remove(), size(), contains(), set()for-each and IteratorHashSet – no duplicates, no guaranteed order; backed by a hash tableLinkedHashSet – no duplicates, preserves insertion orderTreeSet – no duplicates, elements stored in natural sorted orderQueue interface – FIFO; offer(), poll(), peek()Stack – LIFO; push(), pop(), peek()Vector – legacy thread-safe version of ArrayListHashMap – key-value pairs, no guaranteed order, allows one null keyLinkedHashMap – key-value pairs, preserves insertion orderput(), get(), remove(), containsKey(), keySet(), values()Comparable interface – compareTo() for natural ordering inside the classComparator interface – compare() for custom ordering defined outside the classCollections.sort(list) and Collections.sort(list, comparator)Iterator – hasNext() and next() for safe manual traversalWhy This Module Matters: Before you can test an API, you need to understand what it is and why it exists. This foundation shapes every decision you make as a tester — from what to test, to how to document bugs, to how you explain your work in interviews.
Why This Module Matters: Every single API test you write is based on an HTTP method. Knowing which method to use and what it means is the difference between writing meaningful tests and just clicking Send and hoping for the best.
Why This Module Matters: Status codes are the first thing you check in every test result. A tester who can read a three-digit code and instantly know whether the problem is in the request, the server, or the data is worth far more than one who just checks “did I get a response?”
Why This Module Matters: A complete test validates more than just the response body. Headers, status lines, response time, and parameter types all matter — and knowing every part of a request and response means you catch bugs that less thorough testers miss entirely.
https://api.example.com/v1/users/42/users/{id} — identifies a specific record? for filtering or searching: /products?category=books&limit=10Content-Type: application/json, Authorization: Bearer <token>HTTP/1.1 201 CreatedContent-Type, Cache-Control, X-Request-IdWhy This Module Matters: Almost every modern API sends and receives JSON. If you can’t read and write JSON confidently, you can’t write meaningful request bodies or validate response data accurately. This module is the difference between surface-level testing and deep, reliable testing.
{ "id": 1, "name": "Bhanu", "active": true }["admin", "viewer", "editor"], array of objects:[ { ... }, { ... } ]true / false), null, nested Object, ArrayWhy This Module Matters: Postman is the standard tool for API testing in the industry. Getting comfortable with its interface from day one means you spend your time testing — not fighting the tool. Most QA job descriptions now list Postman as a required skill.
Why This Module Matters: No professional tester hardcodes URLs and tokens into every request. Collections keep your work organised and shareable; environments let the same test run against Dev, Staging, or Production with a single switch; variables make your tests dynamic and reusable.
{{base_url}}, {{token}}{{variable_name}} in URL, header value, or bodypm.environment.set("userId", pm.response.json().id)Why This Module Matters: Most real-world APIs are secured. If you can’t handle authentication in Postman, you can’t test 80% of a real application. Understanding auth also helps you write better security-related negative test cases — which is something every interviewer asks about.
x-api-key: abc123 or as a query parameterAuthorization: Bearer <jwt_token>{{access_token}} — never hardcode tokens in requestspm.environment.set("token", ...)Why This Module Matters: A tester who only checks the happy path misses half the bugs. APIs fail in predictable ways — bad inputs, missing auth, wrong permissions, nonexistent resources. Testing these “expected failure” scenarios is what makes a QA engineer genuinely valuable to a team.
Why This Module Matters: Manual checking — reading the response and deciding if it’s right — doesn’t scale. Test scripts run automatically after every request and give you a pass/fail result instantly. This is what separates a manual tester from a semi-automated API tester, and it’s a skill employers specifically look for.
pm.test("description", function () { ... }) — structure of every Postman test casepm.response.to.have.status(201) — assert the exact status code returnedpm.response.to.have.header("Content-Type") — assert a specific header is presentpm.response.responseTime < 2000 — assert response is under 2 secondsconst json = pm.response.json() — parse response body as a JavaScript objectpm.expect(json.name).to.eql("Bhanu") — assert exact field valuepm.expect(json).to.have.property("id") — assert a key exists in the responsepm.expect(json.id).to.be.a("number") — assert correct data typepm.expect(json.items).to.be.an("array").that.is.not.empty — assert non-empty array.to.include, .to.not.be.null, .to.be.true, .to.be.above(0)Why This Module Matters: Real test scenarios require setup — unique data, fresh tokens, IDs from previous responses. Pre-request scripts automate this setup so your test suite is self-sufficient and repeatable. Without this skill, you end up manually copying values between requests, which defeats the purpose of automation.
pm.environment.set("email", "user" + Date.now() + "@test.com")id → store as {{userId}} → use in GET /users/{{userId}}Why This Module Matters: Running one request at a time isn’t testing — it’s clicking. Collection Runner lets you run your entire test suite in one go and see a complete pass/fail summary. Pairing it with a CSV data file means you can test 50 different inputs without writing 50 separate requests.
{{column_name}} in URL, body, and headers — same request runs with different data each timeWhy This Module Matters: Knowing Postman as a tool isn’t enough. Having a test strategy is a professional skill. Companies hire testers who can look at API documentation, build a complete test plan, organize their work, and plug it into a daily pipeline — not just testers who know how to click Send.
newman run collection.json -e environment.jsonGET vs POST — GET retrieves with no body; POST creates with a body; GET is idempotent (safe to repeat), POST is not
401 vs 403 vs 404 —
PUT vs PATCH — PUT replaces the whole resource; PATCH updates only specified fields
What do you validate? — Status code, response body fields and types, required keys present, response time, content type header
Bearer Token Flow — POST /login → receive token → store → use in header:Authorization: Bearer {{token}}
Data-driven testing — Upload CSV to Collection Runner; each row becomes one test iteration; {{column}} variables pull in each row’s data automatically
try block – code that may throw an exceptioncatch (ExceptionType e) – handling a specific exception typecatch blocks – handling different exception types separatelyfinally block – always executes; used for resource cleanup (closing files, connections)throw keyword – manually throwing an exception from your codethrows keyword – declaring that a method may throw a checked exceptionNullPointerExceptionArrayIndexOutOfBoundsExceptionNumberFormatExceptionArithmeticExceptionArrayList – dynamic array; fast random access; allows duplicates; maintains insertion orderLinkedList – doubly-linked list; fast add/remove at ends; slower random accessadd(), get(int), remove(), size(), contains(), set()for-each and IteratorHashSet – no duplicates, no guaranteed order; backed by a hash tableLinkedHashSet – no duplicates, preserves insertion orderTreeSet – no duplicates, elements stored in natural sorted orderQueue interface – FIFO; offer(), poll(), peek()Stack – LIFO; push(), pop(), peek()Vector – legacy thread-safe version of ArrayListHashMap – key-value pairs, no guaranteed order, allows one null keyLinkedHashMap – key-value pairs, preserves insertion orderput(), get(), remove(), containsKey(), keySet(), values()Comparable interface – compareTo() for natural ordering inside the classComparator interface – compare() for custom ordering defined outside the classCollections.sort(list) and Collections.sort(list, comparator)Iterator – hasNext() and next() for safe manual traversalKoding Tree offers comprehensive training in Advanced Selenium, API Manual Testing, Rest Assured, DevOps, and Java, covering everything from core fundamentals to advanced automation and system-level concepts
💡 Why this matters: Most testers use only basic TestNG. Mastering @DataProvider, @Factory, and dependsOnMethods lets you run smarter, data-driven, and highly controlled test suites — skills that immediately impress in interviews.
@BeforeSuite, @BeforeTest, @BeforeClass, @BeforeMethod, @AfterMethod, @AfterClass, @AfterSuiteinvocationCount – running a test method multiple times; constraints and valid use casespriority – default value 0; negative values allowed; alphabetical tie-breakingdependsOnMethods – precedence over priority when both are setenabled=false vs alwaysRun=true – controlling test skipping within groupstestng.xml files into one run using <suite-files>Object[] – single-parameter dataset; Object[][] – multi-row multi-column datasetIterator<Object[]> – lazy loading for large datasets without loading everything into memoryMap is not a valid @DataProvider return typeAssert vs SoftAssert – fail-fast vs collect-all-failures strategy@Test(groups) – smoke, regression, sanity; running specific groups from testng.xml@Parameters – passing values from testng.xml into test methods at runtime@Factory – dynamically generating multiple test class instances from a single classTestNG and XmlSuite classes – no XML needed💡 Why this matters: Dependency Injection is how enterprise frameworks avoid duplicating browser setup across dozens of test classes. Understanding java.lang.reflect makes you stand out in senior-level framework design interviews.
WebDriver into test classes via constructor or method parametersjava.lang.Class, java.lang.reflect.Method – inspecting and invoking methods at runtimeWebDriver – when to use each approach in real projects💡 Why this matters: Flaky tests cost teams hours of manual re-runs. Implementing IRetryAnalyzer and ITestListener at the framework level means your suite handles failures automatically — a hallmark of a production-ready framework.
IRetryAnalyzer – implementing retry(ITestResult) to auto re-run failed tests up to a configurable limitITestListener – hooking into onTestFailure(), onTestStart(), onTestSuccess() lifecycle eventsITestResult + TakesScreenshot + FileUtils.copyFile()ExtentReports via Base64 encodingReporter.log() – adding custom step messages visible in the TestNG HTML report@Listeners annotation or the <listeners> block in testng.xml💡 Why this matters: Design patterns are asked in virtually every senior QA interview. Learning to implement and explain them with real Selenium examples puts you ahead of most candidates.
WebDriver instance for the entire test runDriverFactory class – returning ChromeDriver, FirefoxDriver, or EdgeDriver based on input parameterif-else logic from individual test classesEventFiringWebDriver + implementing WebDriverEventListenerEventFiringDecorator wrapping WebDriver + WebDriverListener interfaceclick(), navigate().to(), and exception automatically through the listenerextends AbstractWebDriverEventListener vs implements WebDriverListener💡 Why this matters: Standard POM is just the beginning. Advanced annotations like @FindAll, @FindBys, and @CacheLookup make your page classes faster and more expressive — and interviewers notice the difference.
@FindBy – declaring WebElement and List<WebElement> fields, initialized via PageFactory.initElements(driver, this)@FindAll – locating elements matching any of multiple locators (OR logic)@FindBys – locating elements matching all of multiple locators (AND / parent-child chaining)@CacheLookup – caching the element reference after the first DOM lookup to improve performance@CacheLookup helps vs. when it breaks – dynamic elements, page refresh, AJAX updates@FindAll vs @FindBys – logic difference and when to use each in real tests💡 Why this matters: Knowing three different screenshot approaches — and when each is appropriate — shows depth of knowledge. Most testers only know one method, and interviewers notice.
TakesScreenshot – casting WebDriver and calling getScreenshotAs(OutputType.FILE) for full-page captureFileUtils.copyFile() using timestamped filenames to avoid overwritingWebElement.getScreenshotAs() – capturing just a specific element on the page (Selenium 4)AShot library – full-page screenshots including content below the visible foldRobot class (java.awt.Robot) – OS-level desktop screenshot using createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()))ITestListener.onTestFailure(ITestResult) – no test-level code needed💡 Why this matters: Some elements simply cannot be handled by standard Selenium — hidden inputs, custom widgets, OS-level dialogs. JavascriptExecutor and Robot are what professionals reach for when Selenium hits a wall.
WebDriver to JavascriptExecutor and calling executeScript(String, Object...)window.scrollBy(0, 500); scrolling to element: arguments[0].scrollIntoView()WebElement.click() cannot reach: arguments[0].click()arguments[0].value='text' for blocked input fieldsreturn arguments[0].value / return arguments[0].textContentRobot.mouseMove(x, y), mousePress(InputEvent.BUTTON1_DOWN_MASK), mouseRelease()Robot.keyPress(KeyEvent.VK_ENTER) – keyboard simulation at OS levelStringSelection and Toolkit.getDefaultToolkit().getSystemClipboard() for clipboard operations💡 Why this matters: Professional testers don’t just run tests — they produce shareable evidence. Rich HTML reports and structured log files let your team and stakeholders see exactly what was tested, what passed, and why something failed — with zero manual effort.
ExtentSparkReporter and ExtentReports instance in a base class or listenerExtentTest nodes per test and logging pass(), fail(), skip() with messagesITestListener for automatic lifecycle-driven reportingextent.flush()log4j2.xml / log4j.properties – configuring ConsoleAppender, FileAppender, and log patternsLogManager.getLogger(ClassName.class) – logging at DEBUG, INFO, WARN, ERROR levelsReporter.log() – embedding step-level messages directly into the TestNG HTML reportReporter.getOutput(ITestResult) – reading Reporter messages to attach to ExtentReportextends keyword – child class inherits all non-private members of the parentsuper keyword – calling the parent class constructor or methodsprivate, protected, public, package-private – scope of eachprivate fields with public getter and setter methods@Override annotation – compile-time check that overriding is validAnimal a = new Dog() – always safeDog d = (Dog) a – requires instanceof checkinstanceof operator – safely checking type before castinginterface keyword – defines a contract of method signatures without implementationimplements keyword – a class agrees to provide all interface methodspublic abstract, fields are public static finalabstract class – cannot be instantiated; must be subclassedabstract method – declared without a body; subclass must provide implementationString is immutable – every operation creates a new object in the String Poollength(), charAt(int), indexOf(String), lastIndexOf()substring(int start), substring(int start, int end)toUpperCase(), toLowerCase(), trim()replace(), contains(), startsWith(), endsWith()equals() vs equalsIgnoreCase() vs == – why == compares references, not contentsplit(String regex), join(), toCharArray()StringBuilder – mutable, not thread-safe, faster for single-threaded useappend(), insert(), delete(), reverse(), toString()StringBuffer – mutable, thread-safe, used in multi-threaded programsString vs StringBuilder vs StringBuffer – performance and thread-safety trade-offsArrayList – dynamic array; fast random access; allows duplicates; maintains insertion orderLinkedList – doubly-linked list; fast add/remove at ends; slower random accessadd(), get(int), remove(), size(), contains(), set()for-each and IteratorHashSet – no duplicates, no guaranteed order; backed by a hash tableLinkedHashSet – no duplicates, preserves insertion orderTreeSet – no duplicates, elements stored in natural sorted orderQueue interface – FIFO; offer(), poll(), peek()Stack – LIFO; push(), pop(), peek()Vector – legacy thread-safe version of ArrayListHashMap – key-value pairs, no guaranteed order, allows one null keyLinkedHashMap – key-value pairs, preserves insertion orderput(), get(), remove(), containsKey(), keySet(), values()Comparable interface – compareTo() for natural ordering inside the classComparator interface – compare() for custom ordering defined outside the classCollections.sort(list) and Collections.sort(list, comparator)Iterator – hasNext() and next() for safe manual traversalWhy this matters: A Keyword Driven Framework separates test logic from test data – so QA analysts without coding skills can write test cases in Excel and the framework executes them automatically. This is a sign of a senior framework developer.
clickElement(), typeText(), verifyText(), navigateTo()
Why this matters: A working project on a real application is the difference between a resume and a portfolio. You leave this module with something you can demo, explain end-to-end, and be proud of in any senior QA interview.
@FindBy, ExtentReports, Log4j, Excel data, Jenkins CI/CDDesign Patterns
Explain Singleton, Factory, Decorator with real code examples from your own project
Framework Walkthrough
Walk through your package structure, layer responsibilities, and why each design decision was made
CI/CD Pipeline
Describe the full chain: Jenkins → pom.xml → testng.xml → @Parameters → test method
Parallel Execution
Explain ThreadLocal<WebDriver> and how you prevented driver conflicts across parallel threads
Data Strategies
Compare Excel, JSON, Properties, MySQL — and justify where you used each in the project
Docker & Grid
Describe how you used Docker containers as browser nodes and ran tests without installing browsers locally
pom.xml structureWebDriver for Chrome, Firefox, and Edge browsersdriver.get() and driver.navigate().to() – loading URLsnavigate().back(), navigate().forward(), navigate().refresh()driver.manage().window().maximize(), setSize(), setPosition()driver.getTitle() and driver.getCurrentUrl() for page verificationdriver.quit() vs driver.close() – when to use each💡 Locators are how your script finds elements on a page. Mastering all 8 strategies means you can automate any website, no matter how it is built.
By.id – fastest and most reliable when availableBy.name – using the HTML name attributeBy.className – single CSS class targetingBy.tagName – selecting by HTML element typeBy.linkText – exact anchor text matchingBy.partialLinkText – partial anchor text matchingBy.cssSelector – powerful CSS-based targetingBy.xpath – most flexible, works anywhere in the DOM💡 CSS Selectors and XPath are the two most powerful locator types. Knowing both in depth allows you to find any element — even in the most complex web pages.
input[type='text'][name='email']:nth-child(), ^=, $=, *= – starts-with, ends-with, contains patterns//tag[@attribute='value']contains(), starts-with(), text() functionsparent, child, following-sibling, preceding-sibling, ancestor(//tag)[2]💡 Once you find an element, you need to interact with it – type, click, read values. These are the core actions every automation script performs.
sendKeys() – typing into text fields and input boxesclick() – clicking buttons, links, checkboxes, and radio buttonsclear() – clearing existing text from input fieldssubmit() – submitting forms directlyisSelected() – checking state of checkboxes and radio buttonsisEnabled() – verifying if a field or button is activeisDisplayed() – checking if an element is visible on screengetText() – reading the visible text of any elementgetAttribute() – reading any HTML attribute valuegetCssValue() – reading applied CSS property values💡 Many modern websites require mouse gestures and keyboard combos that a simple click cannot handle. The Actions class and screenshot tools cover exactly these scenarios.
moveToElement() – hovering over menus and tooltipsdoubleClick() and contextClick() (right-click)dragAndDrop() and dragAndDropBy()keyDown(Keys.SHIFT), keyUp(), sendKeys(Keys.ENTER)scrollToElement() and scrollByAmount() (Selenium 4)build().perform() – chaining and executing action sequencesTakesScreenshot interface – full-page screenshot on test failureWebElement.getScreenshotAs()💡 Real applications open pop-ups, new tabs, and embed content in frames. Knowing how to switch between them keeps your scripts from getting stuck.
driver.getWindowHandle() – capturing the current window referencedriver.getWindowHandles() – getting all open window/tab referencesdriver.switchTo().window(handle) – switching between windows and tabsnewWindow(WindowType.TAB)driver.switchTo().frame() – switching by index, name, or WebElementdriver.switchTo().defaultContent() – returning to the main pagedriver.switchTo().alert() – handling JavaScript alerts and confirmsalert.accept(), alert.dismiss(), and alert.sendKeys()ClassName obj = new ClassName()this keyword – resolving naming conflicts between parameters and instance fieldsstatic variable – one copy shared across all instances of a classstatic method – belongs to the class, not to any objectfinal variable – constant; must be assigned exactly oncefinal method – cannot be overridden by a subclassfinal class – cannot be extended (e.g., String is a final class)💡 Timing issues cause most automation failures. Proper synchronization makes your scripts reliable — even on slow networks or dynamic pages that load asynchronously.
Thread.sleep() – static wait (why it should be avoided in real scripts)driver.manage().timeouts().implicitlyWait() – global element search timeoutWebDriverWait with ExpectedConditions – explicit conditional waitsvisibilityOfElementLocatedelementToBeClickabletextToBePresentInElementalertIsPresentFluentWait – polling interval, custom timeout, ignoring exceptions💡 POM is the industry-standard way to organise automation code. It separates locators from test logic — making scripts easier to maintain when the UI changes.
@FindBy annotation – declaring locators declarativelyPageFactory.initElements(driver, this) – initialising page elementsStaleElementReferenceException💡 TestNG is the test management backbone of most Selenium projects. It controls the order, grouping, and reporting of your tests — making your suite production-quality.
@Test, @BeforeMethod, @AfterMethod, @BeforeClass, @AfterClass, @BeforeSuite, @AfterSuitegroups attribute – running smoke vs regression sets@Parameters and testng.xml configuration@DataProvidertestng.xmldependsOnMethods), and enabled flagReporter.log() inside test methodsAssert – test stops immediately on failureSoftAssert – collect all failures, report at endassertEquals, assertTrue, assertFalse, assertNull, assertNotNull💡 Data-driven testing lets one script run across hundreds of input combinations stored in an Excel sheet — a standard practice in enterprise QA teams.
pom.xml for .xlsx supportXSSFWorkbook, XSSFSheet, XSSFRow, XSSFCell – reading the Excel object hierarchyExcelUtils utility class for the framework
💡 This module brings everything together into a production-level framework — the kind you will actually work with inside a software company.
src/main for utilities, src/test for test scriptsBaseTest class – centralised driver initialisation and teardownRemoteWebDriver – running tests on remote machines and browserspom.xml structureWebDriver for Chrome, Firefox, and Edge browsersdriver.get() and driver.navigate().to() – loading URLsnavigate().back(), navigate().forward(), navigate().refresh()driver.manage().window().maximize(), setSize(), setPosition()driver.getTitle() and driver.getCurrentUrl() for page verificationdriver.quit() vs driver.close() – when to use each💡 Locators are how your script finds elements on a page. Mastering all 8 strategies means you can automate any website, no matter how it is built.
By.id – fastest and most reliable when availableBy.name – using the HTML name attributeBy.className – single CSS class targetingBy.tagName – selecting by HTML element typeBy.linkText – exact anchor text matchingBy.partialLinkText – partial anchor text matchingBy.cssSelector – powerful CSS-based targetingBy.xpath – most flexible, works anywhere in the DOM💡 CSS Selectors and XPath are the two most powerful locator types. Knowing both in depth allows you to find any element — even in the most complex web pages.
input[type='text'][name='email']:nth-child(), ^=, $=, *= – starts-with, ends-with, contains patterns//tag[@attribute='value']contains(), starts-with(), text() functionsparent, child, following-sibling, preceding-sibling, ancestor(//tag)[2]💡 Once you find an element, you need to interact with it – type, click, read values. These are the core actions every automation script performs.
sendKeys() – typing into text fields and input boxesclick() – clicking buttons, links, checkboxes, and radio buttonsclear() – clearing existing text from input fieldssubmit() – submitting forms directlyisSelected() – checking state of checkboxes and radio buttonsisEnabled() – verifying if a field or button is activeisDisplayed() – checking if an element is visible on screengetText() – reading the visible text of any elementgetAttribute() – reading any HTML attribute valuegetCssValue() – reading applied CSS property values💡 Many modern websites require mouse gestures and keyboard combos that a simple click cannot handle. The Actions class and screenshot tools cover exactly these scenarios.
moveToElement() – hovering over menus and tooltipsdoubleClick() and contextClick() (right-click)dragAndDrop() and dragAndDropBy()keyDown(Keys.SHIFT), keyUp(), sendKeys(Keys.ENTER)scrollToElement() and scrollByAmount() (Selenium 4)build().perform() – chaining and executing action sequencesTakesScreenshot interface – full-page screenshot on test failureWebElement.getScreenshotAs()💡 Real applications open pop-ups, new tabs, and embed content in frames. Knowing how to switch between them keeps your scripts from getting stuck.
driver.getWindowHandle() – capturing the current window referencedriver.getWindowHandles() – getting all open window/tab referencesdriver.switchTo().window(handle) – switching between windows and tabsnewWindow(WindowType.TAB)driver.switchTo().frame() – switching by index, name, or WebElementdriver.switchTo().defaultContent() – returning to the main pagedriver.switchTo().alert() – handling JavaScript alerts and confirmsalert.accept(), alert.dismiss(), and alert.sendKeys()ClassName obj = new ClassName()this keyword – resolving naming conflicts between parameters and instance fieldsstatic variable – one copy shared across all instances of a classstatic method – belongs to the class, not to any objectfinal variable – constant; must be assigned exactly oncefinal method – cannot be overridden by a subclassfinal class – cannot be extended (e.g., String is a final class)💡 Timing issues cause most automation failures. Proper synchronization makes your scripts reliable — even on slow networks or dynamic pages that load asynchronously.
Thread.sleep() – static wait (why it should be avoided in real scripts)driver.manage().timeouts().implicitlyWait() – global element search timeoutWebDriverWait with ExpectedConditions – explicit conditional waitsvisibilityOfElementLocatedelementToBeClickabletextToBePresentInElementalertIsPresentFluentWait – polling interval, custom timeout, ignoring exceptions💡 POM is the industry-standard way to organise automation code. It separates locators from test logic — making scripts easier to maintain when the UI changes.
@FindBy annotation – declaring locators declarativelyPageFactory.initElements(driver, this) – initialising page elementsStaleElementReferenceException💡 TestNG is the test management backbone of most Selenium projects. It controls the order, grouping, and reporting of your tests — making your suite production-quality.
@Test, @BeforeMethod, @AfterMethod, @BeforeClass, @AfterClass, @BeforeSuite, @AfterSuitegroups attribute – running smoke vs regression sets@Parameters and testng.xml configuration@DataProvidertestng.xmldependsOnMethods), and enabled flagReporter.log() inside test methodsAssert – test stops immediately on failureSoftAssert – collect all failures, report at endassertEquals, assertTrue, assertFalse, assertNull, assertNotNull💡 Data-driven testing lets one script run across hundreds of input combinations stored in an Excel sheet — a standard practice in enterprise QA teams.
pom.xml for .xlsx supportXSSFWorkbook, XSSFSheet, XSSFRow, XSSFCell – reading the Excel object hierarchyExcelUtils utility class for the framework
💡 This module brings everything together into a production-level framework — the kind you will actually work with inside a software company.
src/main for utilities, src/test for test scriptsBaseTest class – centralised driver initialisation and teardownRemoteWebDriver – running tests on remote machines and browsersMicroservices based airline reservation backend.
Full-featured Amazon clone with Cart & Payment Gateway.
Secure transaction portal with Spring Security & JWT.
Patient records & doctor booking system.