- (), Allure Framework , @Step. , , Spring Guice.
.
, Aspect Advice, .
@Step - . , - @Pointcut , Advice- :
Advice, (@Before);
, Advice (@After, @AfterReturning);
Advice, ( ) (@Around).
, , “” , . , .
Advice - , - - log.
Allure Framework, ( ) , AOP. Allure- - @Step . , , . . , , - .
, - , Allure, . , Lombok, AspectJ Allure . Allure , , . .
Gradle, Maven .
, AspectJ :
compile 'org.aspectj:aspectjrt:1.9.2'
compile ‘org.aspectj:aspectjweaver:1.9.2’
io.qameta.allure:allure-gradle:2.8.1, “aspectjweaver”, .. Allure :
allure {
version = '2.8.1'
autoconfigure = true
allureJavaVersion = '2.13.7'
aspectjVersion = '1.9.2'
configuration = 'compile'
}
, , GitHub.
. , log- , .
, , Google, - ( - - - ).
@Test
public void allureLogTest() {
GoogleSteps.openSearchPage();
GoogleSteps.searchFor("java");
String resultStats = GoogleSteps.getResultStats();
MatcherAssert.assertThat(
" ",
resultStats,
Matchers.equalTo("-")
);
}
, .
(, Selenide, ), , .
@Step, , Allure. .
public class GoogleSteps {
@Step(" ")
@Attachment
public static String getResultStats() {
return Selenide.$("#result-stats").text();
}
@Step(" : {0}")
public static void searchFor(String request) {
Selenide.$("[name='q']").setValue(request);
Selenide.$("[name='btnK']").click();
}
@Step(" ")
public static void openSearchPage() {
Selenide.open("https://www.google.ru/");
}
}
. - , java - @Step.
@Aspect
public class AllureLogAspect {
private static final Logger log = LoggerFactory.getLogger(AllureLogAspect.class);
…
}
pointcut, . , , , io.qameta.allure.Step:
@Before("@annotation(io.qameta.allure.Step) && execution(* *(..))")
public void beforeStep(JoinPoint joinPoint) {
String stepName = getStepName(joinPoint);
log.info("BEGIN: " + stepName);
}
@Before , . (JoinPoint), . :
private String getStepName(JoinPoint joinPoint) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Map<String, Object> parametersMap = getParametersMap(joinPoint);
Method method = methodSignature.getMethod();
Step step = method.getAnnotation(Step.class);
String stepName = step.value();
return Optional.of(stepName)
.filter(StringUtils::isNoneEmpty)
.map(it -> processNameTemplate(it, parametersMap))
.orElse(methodSignature.getName());
}
,
return Optional.of(stepName)
.filter(StringUtils::isNoneEmpty)
.map(it -> processNameTemplate(it, parametersMap))
.orElse(methodSignature.getName());
return stepName;
. , .
?
beforeStep, . .
@AfterReturning:
@AfterReturning(
pointcut = "@annotation(io.qameta.allure.Step) && execution(* *(..))",
returning = "result"
)
public void afterStep(JoinPoint joinPoint, Object result) {
String stepName = getStepName(joinPoint);
log.info("END: " + stepName);
if(result != null) {
log.info("RESULT: " + result);
}
}
, - . , .
. /resources/META-INF - aop-ajc.xml, :
<aspectj>
<aspects>
<aspect name="org.example.aop.aspects.AllureLogAspect"/>
</aspects>
</aspectj>
, , Allure. .
Selenide, listener- . . , HTTP- OpenAPI- Swagger-. AOP Allure. . - SQL- .
.
, . , 2-3 . , .
checkRandom(), 0 9 , desiredValue:
public class CommonSteps {
@Step(", = {0}")
@WithRetries(20)
public static void checkRandom(int desiredValue) {
Random random = new Random();
int i = random.nextInt(10);
MatcherAssert.assertThat(
" ",
i,
Matchers.equalTo(desiredValue)
);
}
}
( ).
, @WithRetries. , , 3 :
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface WithRetries {
int value() default 3;
}
:
@Aspect
public class WithRetriesAspect {
private static final ThreadLocal<Boolean> processingWrapper = ThreadLocal.withInitial(() -> false);
private static final Logger log = LoggerFactory.getLogger(WithRetriesAspect.class);
public static Boolean isProcessing() {
return processingWrapper.get();
}
...
}
, pointcut @Around. , @WithRetries.
@Around("@annotation(org.example.aop.annotations.WithRetries) && execution(* *(..))")
public Object handleRetries(final ProceedingJoinPoint joinPoint) throws Throwable {
processingWrapper.set(true);
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
WithRetries annotation = method.getAnnotation(WithRetries.class);
int retryCount = annotation.value();
Throwable storedException = null;
Object result = null;
boolean processed = false;
int i = 0;
while (!processed && i < retryCount) {
try {
result = joinPoint.proceed();
processed = true;
} catch(Throwable throwable) {
log.warn(" №" +i+":\r\n"+throwable.toString());
storedException = throwable;
}
i++;
}
, .
Advice . , storedException. , - . - , , .
processingWrapper.set(false);
if(!processed) {
assert storedException != null;
throw storedException;
}
return result;
/resources/META-INF/aop-ajc.xml
<aspectj>
<aspects>
<aspect name="org.example.aop.aspects.AllureLogAspect"/>
<aspect name="org.example.aop.aspects.WithRetriesAspect"/>
</aspects>
</aspectj>
- , , .
. :
@Aspect
public class MatcherAssertAspect {
private static final Logger log = LoggerFactory.getLogger(MatcherAssertAspect.class);
…
}
pointcut .
pointcut , assertThat:
@Pointcut("execution(* assertThat(..))")
void inMethods() {
}
pointcut - , org.hamcrest.MatcherAssert:
@Pointcut("execution(* org.hamcrest.MatcherAssert.*(..))")
void inMatcherAssert() {
}
pointcut :
@Pointcut("execution(public * *(..))")
void anyPublic() {
}
pointcut- assertThat org.hamcrest.MatcherAssert.
Advice @Arround:
@Around("anyPublic() && inMatcherAssert() && inMethods()")
public Object handleAssert(final ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
try {
result = joinPoint.proceed();
} catch (Throwable throwable) {
if (WithRetriesAspect.isProcessing()) {
throw throwable;
} else {
log.warn(throwable.toString());
}
}
return result;
}
, .
:
@Test
void errorsSkippingTest() {
MatcherAssert.assertThat("test", true, Matchers.equalTo(false));
MatcherAssert.assertThat("test2", 1, Matchers.equalTo(2));
MatcherAssert.assertThat("test3", "olol", Matchers.equalTo("pishpish"));
}
/resources/META-INF/aop-ajc.xml
<aspectj>
<aspects>
<aspect name="org.example.aop.aspects.AllureLogAspect"/>
<aspect name="org.example.aop.aspects.MatcherAssertAspect"/>
<aspect name="org.example.aop.aspects.WithRetriesAspect"/>
</aspects>
</aspectj>
- Flaky-. , ( , ). , .
Allure - @Flaky. , , . . , StackTrace , .
, - - , , Kibana, .. , Kibana . , , . AOP.
: .
P.S. . VK, FB, Instagram Telegram-, Maxilect.