Maven + AspectJ + TestNG + 硒

Maven + AspectJ + TestNG + Selenium

我正在尝试将所有这些工具组合在一起。 这是我的项目的详细信息和一些屏幕截图。 我需要 post-编译时编织我的源代码。

注解:

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

看点:

@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();
  }
}

页数:

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();
  }
}

测试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>

建议无效,但测试通过。 我尝试了不同的 aspectj 库版本。 我错过了什么让它发挥作用?

您的 POM、方面和测试代码中有几处可以改进。但问题的根本原因是方面首先由 AspectJ Maven 插件编织到测试 class 中,但随后由于相当繁琐的 Maven 编译器默认配置而被 Maven 编译器插件覆盖,导致它重新编译所有内容。因此,您需要将此添加到您的 Maven 编译器配置中:

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

您可以在 中找到解释。

其他需要改进的地方:

  • 升级到支持 Java 11
  • 的更新的 AspectJ Maven 版本
  • 将 AspectJ 依赖项升级到 1.9.7
  • 摆脱 aspectjweaver 依赖项和 aop.xml,因为您已经使用了编译时织入并且不需要在此之上的加载时织入配置。要么这个要么那个,但不能两者兼而有之。
  • 使 aspectjtools 成为 Maven 编译器依赖项,而不是 Maven 模块本身的依赖项。您只需要插件内的编译器,而不是在运行时。那里,aspectjrt就够了。
  • 细化你的切入点以仅包含 execution() 个连接点,否则每个方面建议将被触发两次,一次用于 execution,一次用于 call。当 运行 测试时,你可以在控制台上看到这个。
  • 为 AspectJ Maven 激活 <showWeaveInfo>true</showWeaveInfo>。那么你也可以看到之前的问题,即doubly woven advice,在编译时更清楚。
  • 增强测试以同时单击 cookie 横幅,这在我的案例中是必要的,以便在测试期间甚至能够单击搜索按钮。它还为 @Click 触发方面添加了第二个测试用例。
  • 在我的例子中,我不得不退出驱动程序,而不仅仅是关闭它。否则,我最终会得到几十个 chromedriver.exe 后台进程。
<?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");
  }
}

控制台日志应为:

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