Home > database >  Maven AspectJ TestNG Selenium
Maven AspectJ TestNG Selenium

Time:10-28

I'm trying to combine all these tools together. Here are the details and some screenshots of my project. I need post-compile time weave my source code.

Annotation:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Click {}

Aspect:

@Aspect
public class ClickAspect {

  @Pointcut("@annotation(com.selenium.aspect.support.annotation.Click)")
  public void clickAnn() {}

  @Around("clickAnn()")
  public void clickOnAction(ProceedingJoinPoint joinPoint) throws Throwable {
      System.out.println("Clicking on a button");
      joinPoint.proceed();
  }
}

Page:

public class Page {

  @FindBy(id = "menu-item-40489")
  private WebElement search;

  public Page(WebDriver driver) {
      PageFactory.initElements(driver, this);
  }

  @Click
  public void clickOnSearch() {
      search.click();
  }
}

Test class:

public class SeleniumAspectSupportTest {

  private WebDriver driver;
  private Page page;

  @BeforeTest
  public void initDriver() {
      System.setProperty("webdriver.chrome.driver", "src/main/resources/chromedriver.exe");
      driver = new ChromeDriver();
      driver.manage().window().maximize();
      driver.manage().timeouts().pageLoadTimeout(40, TimeUnit.SECONDS);
      driver.manage().timeouts().implicitlyWait(120, TimeUnit.SECONDS);

      page = new Page(driver);
  }

  @AfterTest
  public void dropDriver() {
      driver.close();
  }

  @Test
  public void simpleTest() {
      driver.get("https://www.baeldung.com");
      page.clickOnSearch();
      System.out.println("DONE");
  }
}

pom.xml:

<properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
</properties>

<dependencies>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.9.2</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.2</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjtools</artifactId>
        <version>1.9.2</version>
    </dependency>
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.4.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>3.141.59</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>11</source>
                <target>11</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.11</version>
            <configuration>
                <complianceLevel>11</complianceLevel>
                <source>11</source>
                <target>11</target>
            </configuration>
            <executions>
                <execution>
                    <phase>process-sources</phase>
                    <goals>
                        <goal>compile</goal>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

aop.xml:

<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
  <aspects>
    <aspect name="com.selenium.aspect.support.controller.ClickAspect"/>
  </aspects>
</aspectj>

The advise is not working, however the test passes. I've tried different aspectj library versions. What have I missed to make it work?

CodePudding user response:

There are several things which could be improved in your POM, aspect and test code. But the root cause of your problem is that the aspect is first woven into the test class by AspectJ Maven Plugin, but then overwritten by Maven Compiler Plugin due to a rather cumbersome Maven Compiler default configuration, causing it to recompile everything. Therefore, you need to add this to your Maven Compiler configuration:

<!-- IMPORTANT -->
<useIncrementalCompilation>false</useIncrementalCompilation>

I You can find an explanation in my answer here.

Other things you should improve:

  • Upgrade to a more recent AspectJ Maven version supporting Java 11
  • Upgrade AspectJ dependencis to 1.9.7
  • Get rid of the aspectjweaver dependency and aop.xml, because you already use compile-time weaving and do not need a load-time weaving configuration on top of that. Either this or that, bot not both.
  • Make aspectjtools a Maven Compiler dependency rather than a dependency for the Maven module itself. You only need the compiler inside the plugin, not during runtime. There, aspectjrt is enough.
  • Refine your pointcut to only include execution() joinpoints, because otherwise each aspect advice will be triggered twice, once for execution and once for call. You can see this on the console when running the test.
  • Activate <showWeaveInfo>true</showWeaveInfo> for AspectJ Maven. Then you can also see the previous problem, i.e. doubly woven advice, more clearly during compile time.
  • Enhance the test to also click away the cookie banner, which was necessary in my case in order to even be able to click the search button during the test. It also adds a second test case for @Click triggering the aspect.
  • In my case I had to quit the driver, not just close it. Otherwise, I would end up with dozens of chromedriver.exe background processes.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>SO_AJ_TestNGSelenium_69744638</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <aspectj.version>1.9.7</aspectj.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>${aspectj.version}</version>
    </dependency>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>7.4.0</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>3.141.59</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>11</source>
          <target>11</target>
          <!-- IMPORTANT -->
          <useIncrementalCompilation>false</useIncrementalCompilation>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <version>1.14.0</version>
        <configuration>
          <complianceLevel>11</complianceLevel>
          <source>11</source>
          <target>11</target>
          <showWeaveInfo>true</showWeaveInfo>
        </configuration>
        <executions>
          <execution>
            <phase>process-sources</phase>
            <goals>
              <goal>compile</goal>
              <goal>test-compile</goal>
            </goals>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>${aspectj.version}</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>

</project>
package com.selenium.aspect.support.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Click {}
package org.example;

import com.selenium.aspect.support.annotation.Click;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class Page {
  @FindBy(className = "css-47sehv")
  private WebElement cookiesAgree;

  @FindBy(id = "menu-item-40489")
  private WebElement search;

  public Page(WebDriver driver) {
    PageFactory.initElements(driver, this);
  }

  @Click
  public void clickOnCookiesAgree() {
    cookiesAgree.click();
  }

  @Click
  public void clickOnSearch() {
    search.click();
  }
}
package org.example;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class ClickAspect {
  @Pointcut("@annotation(com.selenium.aspect.support.annotation.Click) && execution(* *(..))")
  public void clickAnn() {}

  @Around("clickAnn()")
  public void clickOnAction(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println(joinPoint   " -> Clicking on a button");
    joinPoint.proceed();
  }
}
package org.example;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import java.util.concurrent.TimeUnit;

public class SeleniumAspectSupportTest {

  private WebDriver driver;
  private Page page;

  @BeforeTest
  public void initDriver() {
    System.setProperty("webdriver.chrome.driver", "src/main/resources/chromedriver.exe");
    driver = new ChromeDriver();
    driver.manage().window().maximize();
    driver.manage().timeouts().pageLoadTimeout(40, TimeUnit.SECONDS);
    driver.manage().timeouts().implicitlyWait(120, TimeUnit.SECONDS);
    page = new Page(driver);
  }

  @AfterTest
  public void dropDriver() {
    driver.close();
    driver.quit();
  }

  @Test
  public void simpleTest() {
    driver.get("https://www.baeldung.com");
    page.clickOnCookiesAgree();
    page.clickOnSearch();
    System.out.println("DONE");
  }
}

The console log should read:

execution(void org.example.Page.clickOnCookiesAgree()) -> Clicking on a button
execution(void org.example.Page.clickOnSearch()) -> Clicking on a button
  • Related