All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.newmainsoftech.aspectjtuil.testutil.junit.JUnitAssistAspect Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012-2013 NewMain Softech
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package com.newmainsoftech.aspectjtuil.testutil.junit;

import java.lang.reflect.UndeclaredThrowableException;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.newmainsoftech.aspectjutil.adviseutil.Util;

/**
 * Helper aspect for JUnit test.  
 * 
 * 

Usage example

*
    *
  • To get test name
    *
      *
    • Background:
      * In JUnit 3.x, the name of current test was easily obtained with JUnit's getName method: *
      String testName = this.getName();
      * With JUnit 4, you need to use @Rule or @Interceptor annotation with * TestName class object.
      *
      *
    • *
    • By just adding this JUnitAssistAspect class (aspectjutil-testutil.jar) to the project's aspect-path * (and, of course, AspectJ's runtime library, SLF4J's API jar and binding jar files in runtime classpath, * additionally to either compiling with AJC for CTW or aop.xml for LTW), no matter the version of JUnit * you're using, the name of the current test can be simply obtained by: *
      * String testName = JUnitAssistAspect.getTestName(); *
      * For further info, see {@link #getTestName()} method.
      *
      *
    • *
    • Limitation
      * If your test method spawning other thread, and call {@link #getTestName()} method from * spawned thread, then it will return null as test name instead of actual test name. *
    • *
    *
  • *
  • To log entrance and exit of test
    * By just adding this JUnitAssistAspect class (aspectjutil-testutil.jar) to the project's aspect-path, * entrance and exit of test will be logged like: *
    * * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    * STARTS TEST: test_SysPropExt_addText
    *     ...
    * ENDS TEST: test_SysPropExt_addText
    * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< *
    *
    *
  • *
* * @author Arata Y. */ @Aspect public class JUnitAssistAspect { private static ThreadLocal testNameThreadLocal = new ThreadLocal(); protected static ThreadLocal getTestNameThreadLocal() { return testNameThreadLocal; } /** * Get name of running test. * This works as long as being called from main thread running each JUnit test even multiple * JUnit tests running concurrently. * But this does not work when called from child worker thread spawned during a test. To support * the call from child worker thread spawned during a test, you may make your test class implemented * {@link JUnitAssistContract} interface and implement custom logic for * {@link JUnitAssistContract#getRunningTestName()} method. * @return name of running test, or null when called from child thread spawned during test. */ public static String getTestName() { String testName = null; MethodSignature methodSignature = testNameThreadLocal.get(); if ( methodSignature == null) { // Avoid memory leakage for either case of having called not during test by mistake // or having called from thread spawned during test testNameThreadLocal.remove(); } else { testName = testNameThreadLocal.get().getName(); if ( testName == null) { // Avoid memory leakage for either case of having called not during test by mistake // or having called from thread spawned during test testNameThreadLocal.remove(); } } return testName; } /** Dummy method for {@link Pointcut} what cross-cut execution of test method. */ @Pointcut( value="execution( @org.junit.Test * *.*()) || execution( * junit.framework.TestCase+.test*())") public static void pointcutOnExecutionOfJUnitTestMethod() {} /** Dummy method for {@link Pointcut} what cross-cut below execution of test method. */ @Pointcut( value="cflowbelow( pointcutOnExecutionOfJUnitTestMethod())") public static void pointcutOnSubsequentialExecutionOfJUnitTestMethod() {} /** * Dummy method for {@link Pointcut} what cross-cut top most execution of test method. * This Pointcut is advised by * {@link #beforeAdvisedTopMostExecutionOfJUnitTestMethod(JoinPoint)} and * {@link #afterAdvisedTopMostExecutionOfJUnitTestMethod(JoinPoint)}. */ @Pointcut( value="pointcutOnExecutionOfJUnitTestMethod() " + "&& !pointcutOnSubsequentialExecutionOfJUnitTestMethod() " + "&& !execution( @org.junit.Ignore * *.*()) " + "&& !cflow( adviceexecution())") public static void pointcutOnTopMostExecutionOfJUnitTestMethod() {} /** * {@link Before} advise method to preserve test method name and to log entrance of test method. * There shouldn't be necessity of calling this method intentionally. * * @param joinPoint * @throws Throwable * @see JUnitAssistAspect#pointcutOnTopMostExecutionOfJUnitTestMethod() */ @Before( value="pointcutOnTopMostExecutionOfJUnitTestMethod()") public void beforeAdvisedTopMostExecutionOfJUnitTestMethod( JoinPoint joinPoint) throws Throwable { MethodSignature methodSignature = (MethodSignature)(joinPoint.getSignature()); JUnitAssistAspect.getTestNameThreadLocal().set( methodSignature); Object target = joinPoint.getTarget(); Class targetClass = target.getClass(); if ( target instanceof JUnitAssistContract) { JUnitAssistContract jUnitAssist = (JUnitAssistContract)target; try { jUnitAssist.setRunningTestName( methodSignature.getName()); } catch( Throwable throwable) { if ( Util.isExceptionChecked( methodSignature, throwable)) { throw throwable; } else { throw new UndeclaredThrowableException( throwable, String.format( "Occured at beforeAdvisedTopMostExecutionOfJUnit4TestMethod " + "advise method of %1$s aspect", JUnitAssistAspect.class.toString() ) ); } } } // Log entrance to test method Logger logger = LoggerFactory.getLogger( target.getClass()); if ( logger.isInfoEnabled()) { logger.info( String.format( "%n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>%n" + "STARTS TEST: %1$s", methodSignature.getName() ) ); } } /** * {@link After} advise method to log exit of test method. * There shouldn't be necessity of calling this method intentionally. * * @param joinPoint * @see JUnitAssistAspect#pointcutOnTopMostExecutionOfJUnitTestMethod() */ @After( value="pointcutOnTopMostExecutionOfJUnitTestMethod()") public void afterAdvisedTopMostExecutionOfJUnitTestMethod( JoinPoint joinPoint) { // Log exit from test method Logger logger = LoggerFactory.getLogger( joinPoint.getTarget().getClass()); if ( logger.isInfoEnabled()) { logger.info( String.format( "%nENDS TEST: %1$s%n" + "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", JUnitAssistAspect.getTestName() ) ); } JUnitAssistAspect.getTestNameThreadLocal().remove(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy