Skip to main content

Reflection & Annotations

Reflection & Annotations for Automation Testing (How Frameworks Work Internally)​


Context (Why this topic exists NOW)​

By now, your automation framework:

  • runs reliably in CI
  • uses TestNG/JUnit annotations
  • supports listeners, retries, and reports

A natural question appears: How do frameworks discover tests and execute them without explicit calls?

Selenium does not provide this. Java Reflection and Annotations explain how automation frameworks work internally.


What Selenium Cannot Do (The Gap)​

Selenium can:

  • execute browser commands

Selenium cannot:

  • discover test classes dynamically
  • invoke methods without direct calls
  • read metadata like annotations
  • build execution flow automatically

This logic is handled entirely by Java.


What Reflection & Annotations Add (The Fix)​

They allow frameworks to:

  • inspect classes at runtime
  • detect annotations
  • invoke methods dynamically
  • control execution flow without hardcoding

In simple words:

Selenium executes steps.
Reflection decides what steps to execute.


What Are Annotations (Automation View)​

Annotations are metadata, not logic.

Examples you already use:

  • @Test
  • @BeforeMethod
  • @AfterMethod
  • @DataProvider

They tell the framework:

  • what a method represents
  • when it should be executed

How TestNG/JUnit Use Annotations (Conceptual)​

At runtime:

  1. Framework scans classes
  2. Finds methods with @Test
  3. Determines execution order
  4. Invokes methods using reflection

You never call test methods manually.


What Is Reflection (Automation View)​

Reflection allows Java to:

  • inspect classes, methods, fields at runtime
  • call methods dynamically
  • access metadata (annotations)

Example:

Method method = testClass.getDeclaredMethod("loginTest");
method.invoke(instance);

Frameworks use this extensively.


Why Automation Engineers Should Care​

Reflection explains:

  • why annotations work
  • how listeners hook into execution
  • how retry logic intercepts failures
  • how custom frameworks are built

You don’t write reflection daily, but you benefit from understanding it.


Custom Annotations (Awareness Level)​

Example:

@Retention(RUNTIME)
@Target(METHOD)
public @interface SmokeTest {
}

Used to:

  • tag tests
  • filter execution
  • build custom runners

Mostly framework-level, not test-level.


Where Reflection Is Used in Automation​

  • Test discovery
  • Listener execution
  • Retry analyzers
  • Dependency injection (light)
  • Reporting hooks

Selenium does none of this.


When NOT to Use Reflection​

❌ Writing test logic with reflection
❌ Over-engineering frameworks
❌ Using reflection where normal code works

Reflection is powerful but dangerous if misused.


Common Mistakes​

  • Treating annotations as executable code
  • Overusing reflection unnecessarily
  • Debugging annotation issues without understanding lifecycle
  • Trying to modify private framework internals

Best Practices (Automation-Approved)​

  • Understand reflection conceptually
  • Let frameworks handle reflection
  • Use annotations as intended
  • Avoid custom reflection-heavy logic unless necessary

Interview Notes​

  • What are annotations?
  • How TestNG/JUnit discover tests
  • Role of reflection in frameworks
  • Difference between compile-time and runtime behavior
  • Why reflection is powerful but risky

Summary (Human Understanding)​

Annotations describe what a method is. Reflection decides when and how to run it.

Frameworks feel magical because reflection is working behind the scenes.