Tuesday, January 14, 2025

automated testing – Unfastened coupling for utility/helper courses


The idea of utility class/capabilities (UFC) is a harmful one, as a result of they have a tendency to finish up breaking the Single Duty Precept, as they’ll have shoppers with fully totally different causes for altering the utility class/operate.

However we are able to lower the chance by decoupling the UFCs from its courses.

There are a number of methods:

1 – Dependency Injection

This fashion, you may simply change implementations of the UFCs:

public class ExampleClass {
    non-public ultimate WaitHelper waitHelper;

    public ExampleClass(WaitHelper waitHelper) {
        this.waitHelper = waitHelper;
    }

    public void performAction() {
        waitHelper.waitForElement();
    }
}

interface WaitHelper {
    void waitForElement();
}

public class DefaultWaitHelper implements WaitHelper {
    public void waitForElement() {
        // Implementation
    }
}

2 – Manufacturing facility Strategies

If the constructions of the utilities is complicated, Manufacturing facility Strategies may help to isolate this complexity:

public class WaitHelperFactory {
    public static WaitHelper createDefault() {
        // Some complicated code right here
        return new DefaultWaitHelper();
    }

    public static WaitHelper createWithCustomTimeout(TimeUnit unit, int worth) {
        // Some complicated code right here
        return new DefaultWaitHelper(unit, worth);
    }
}

Then within the shoppers:

WaitHelper waitHelper = WaitHelperFactory.createDefault();

WaitHelper waitHelper = WaitHelperFactory.createWithCustomTimeout(TimeUnit.MINUTES, 1);

3 – Mixins
Interfaces with default habits may help to share capabilities between courses with out creating static dependencies between them.

public interface WaitHelper {
    default void waitForElement() {
        // Implementation
    }
}

public class ExampleClass implements WaitHelper {
    public void performAction() {
        waitForElement(); // Methodology from the Interface, shared between all WaitHelper derivatives
    }
}

4 – Context objects

If a number of UFCs come collectively, you may inject them as a context object:

@Getter
public class TestContext {
    WaitHelper waitHelper;
    SeleniumUtils seleniumUtils;
}

public class ExampleClass {
    non-public ultimate TestContext context;

    public ExampleClass(TestContext context) {
        this.context = context;
    }

    public void performAction() {
        context.getWaitHelper().waitForElement();
    }
}

5 – Facet-Oriented Programming (AOP)

Cross-cutting considerations, e.g. logging, will be carried out with out creating dependencies utilizing AOP.

E.g.

As an example you’ve got this web page object class

public class LoginPage {
    non-public WebDriver driver;

    // Locators
    non-public By usernameField = By.id("username");
    non-public By passwordField = By.id("password");
    non-public By loginButton = By.id("loginButton");

    public LoginPage(WebDriver driver) {
        this.driver = driver;
    }

    public void enterUsername(String username) {
        driver.findElement(usernameField).sendKeys(username);
    }

    public void enterPassword(String password) {
        driver.findElement(passwordField).sendKeys(password);
    }

    public void clickLogin() {
        driver.findElement(loginButton).click on();
    }
}

You possibly can log the entries and exit outcomes of the usages of the strategies with an Facet like this:

@Facet
@Part
public class LoggingAspect {

    non-public static ultimate Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

    // Pointcut to focus on strategies within the LoginPage class
    @Pointcut("execution(* com.instance.pages.LoginPage.*(..))")
    public void loginPageMethods() {}

    // Log methodology entry
    @Earlier than("loginPageMethods()")
    public void logBefore(JoinPoint joinPoint) {
        logger.data("Getting into methodology: {} with arguments: {}",
                joinPoint.getSignature().getName(),
                joinPoint.getArgs());
    }

    // Log profitable methodology execution
    @AfterReturning(pointcut = "loginPageMethods()", returning = "consequence")
    public void logAfterReturning(JoinPoint joinPoint, Object consequence) {
        logger.data("Methodology executed efficiently: {} with consequence: {}",
                joinPoint.getSignature().getName(),
                consequence);
    }

    // Log exceptions thrown by strategies
    @AfterThrowing(pointcut = "loginPageMethods()", throwing = "error")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
        logger.error("Exception in methodology: {} with message: {}",
                joinPoint.getSignature().getName(),
                error.getMessage());
    }
}

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles

PHP Code Snippets Powered By : XYZScripts.com