본문 바로가기
SpringBoot

일단 써

by 오렌지마끼야또 2024. 12. 19.
728x90
반응형

 

 

 

 

spock 통합테스트를 하려는 과정이다.

 

 

1.

gradle로 실행하는 것과 intellij IDEA(junit) 으로 실행하는게 있다.

(sttings - gradle - run test using 에서 둘중에 하나 고르기)

하지만 gradle로 테스트하면 edit configuration에 세팅한 VM options 를 못 읽는다.

VM options에 jasypt.encryptor.password 를 세팅해놨는데 못읽으니 무용지물이다.

DB 접속정보 jasypt로 암호화해놓음.

그렇다고 build.gradle에 jasypt.encryptor.password 를 박아넣고 push 할 수는 없지 않은가..

gradle 로 하면 reporting도 해줘서 index.html로 결과를 볼 수 있으니 좋긴 하다만 어쩔 수 없다.

intellij IDEA(junit) 로 테스트하자.

이걸로도 결과 파일 뽑을 수 있다.

export test results 누르면 된다.

근데 이걸로 html 다운받으면 희한하게 springboot 로그를 같이 출력한다.. 왜 그렇게 만들었냐 JetBrains

그래서 인터넷 뒤져보다가 github에서 이 html을 만드는 xsl 파일을 찾았다. (올려주신분 압도적 감사)

그래서 그 xsl 파일을 수정해서 로그 출력 안하게 하고, 글씨 크기 바꾸고 깔끔하게 바꿨다.(한줄로 간단하게 썼지만 이 과정도 매우 오래걸렸다.. 어디서 어떻게 출력하는지 명시되어있지 않고 숨겨져 있어서 찾는데 한참 걸림)

export test results 할 때 custom, apply XSL template 선택해서 이 수정한 xsl로 뽑으면 된다.

 

 

 

 

2.

나는 특정 조건에 따라 테스트 클래스에 @SpringBootTest, @DataJpaTest 둘 중에 하나를 적용하고 싶었다.

 

@Conditional 은 스프링 컨텍스트가 확인하는 것이기 때문에 스프링 컨텍스트가 생성된 이후에 동작한다.

@SpringBootTest, @DataJpaTest 이것들이 스프링 컨텍스트를 만드는 어노테이션인데 스프링 컨텍스트가 없는 시점에 이걸 조건적으로 적용하고 싶은거니까 @Conditional 은 못쓴다.

 


컴파일타임에 어노테이션이 고정된다(소스코드가 정해진다)
junit의 @ExtendWith 으로 조건적으로 액티브 프로필을 적용할 순 있다.

@ExtendWith(ConditionalTestExtension.class) 으로 쓰고

ConditionalTestExtension 파일 만들어서 다른 어노테이션의 falg를 읽던, 변수를 읽던 해서 조건 만듦.
하지만 프로필을 여러개 만들어야 하고 각각의 프로필을 사용할 테스트 클래스 또한 여러개 만들어야 한다.

(@ActiveProfiles("AAA"), @SpringBootTest 붙은 클래스 하나, @ActiveProfiles("BBB"), @DataJpaTest 붙은 클래스 하나)

똑같은 코드를 여러개 만드는건 불필요하다.

@ExtendWith는 스프링 컨텍스트가 생성되기 전에 동작하기 때문에 스프링 컨텍스트 없이도 된다.

1. 컴파일타임

     - 어노테이션 고정
2. 런타임

     -  @ExtendWith 확인
     -  정해진 프로필에 따라 실행할 테스트 클래스 결정
     -  클래스에 적용된 어노테이션에 따라 스프링 컨텍스트를 띄우거나 안띄우거나

컴파일타임에 어노테이션을 동적으로 처리하는 방법은 Annotation Processor 를 사용하는 것이다.

위에 썼듯 컴파일타임에 어노테이션이 고정되는건데 Processor 가 먼저 돌아서 조건적으로 어노테이션 정하는 것

 

 

Annotation Processor 동작 과정
컴파일타임. @ABCTest를 감지해서 값에 따라 어노테이션 추가하게 작성해놓음
1. 자바 컴파일러가 소스코드를 컴파일할 때 @ABCTest 애노테이션을 발견
2. SpockTestProcessor가 활성화되어 process() 메서드 실행
3. @ABCTest 의 flag 값에 따라
   - false면 @SpringBootTest 추가
   - true면 @DataJpaTest 추가

 

런타임에는 이미 @SpringBootTest가 추가된 상태로 시작
이후 스프링 테스트 프레임워크는 추가된 @SpringBootTest를 기반으로 스프링 컨텍스트 구성

 

Lombok(롬복)이 이런식으로 동작

 

 

 

@SpringBootTest 애노테이션 처리 과정

● 컴파일 타임
1. Java 컴파일러가 바이트코드로 변환하기 전에 Annotation Processor 동작 (있으면)
2. Java 컴파일러가 소스 코드를 바이트코드로 변환
3. 애노테이션의 문법 검사만 수행
4. @SpringBootTest 등의 애노테이션은 메타데이터로 클래스 파일에 저장

● 런타임 - JUnit 테스트 실행 시
1. JUnit Platform이 테스트 클래스 로드
2. @ExtendWith(SpringExtension.class)에 의해 SpringExtension이 활성화
     - @SpringBootTest에 기본으로 적용되어 있어서 동작하는 @ExtendWith (얘도 있으면 동작)
3. Spring TestContext Framework 동작
     -  TestContextManager가 테스트 컨텍스트 관리
     -  @SpringBootTest 애노테이션 감지
4. SpringBootTestContextBootstrapper 동작
     -  스프링 부트 테스트에 필요한 설정 로드
     -  ApplicationContext 생성 및 구성
5. 애플리케이션 컨텍스트 초기화

 

settings - Annotation Processors 에 Enable annotation processing 체크하래서 했는데 왜 안돼...

-> 성공한 현재 안됐던 이유 파악 : 이 때 만들었던 Annotation Processor는 자바 컴파일러에서 동작하는 것이다. 나는 groovy 테스트코드를 실행했고 때문에 그루비컴파일러가 동작했기 때문에 Annotation Processor가 적용되지 않았다.

빌드 과정을 보면 그루비 컴파일러가 동작한 것을 확인할 수 있다.

 

 

 

런타임에 수정하기

 

@ExtendWith  은 클래스가 JVM에 로드되기 전에 실행되므로 바이트코드 수정 가능

 

Java Agent : JVM이 바이트코드 실행 전에 premain 메서드를 호출, 바이트코드 조작. 왜 안돼...

-> 성공한 현재 안됐던 이유 파악 : 모르겠음. 돼야할 것 같은데 왜 안됐지.

 

 

 

성공!!

런타임에 Groovy의 AST(Abstract Syntax Tree, 추상 구문 트리) Transformation을 사용하여 어노테이션 추가하기

실행 시점
1. Groovy 컴파일러 동작: Groovy 컴파일러가 소스 코드를 분석하고, AST를 생성하며, 지정된 Transformation을 실행합니다.
2. CANONICALIZATION 단계: 이 단계에서 코드 구조가 정리되고, 클래스 간의 상호 참조가 설정됩니다. 이때 커스텀으로 작성한 Transformation이 호출됩니다.

 

주요 CompilePhase 설명:
 - CompilePhase.INITIALIZATION: 초기화 단계로, AST 트리의 최상위 구조가 설정됩니다. 변수 선언 등의 기본적인 구조가 이 단계에서 이루어집니다.
 -  CompilePhase.SEMANTIC_ANALYSIS: 의미 분석 단계로, 변수나 메서드의 타입과 같은 유효성 검사를 합니다. 이 시점에서는 코드가 유효한지 분석하지만, 트리의 구조가 아직 확정되지 않은 상태입니다.
 -  CompilePhase.CANONICALIZATION: 이 시점에서는 AST 트리가 정리되며, 주석, 메서드 호출, 선언된 변수가 최적화되고, 코드가 정리된 후입니다. 변환을 위해 가장 많이 사용되는 시점입니다.
 -  CompilePhase.CLASS_GENERATION: 이 단계는 실제로 바이트코드를 생성하는 시점으로, 트리가 이미 완성된 후입니다. 이 시점 이후에는 트리 구조가 변경될 수 없습니다.

 

컴파일 타임(정적)

@GroovyASTTransformation 로 AST 조작
완료 후 Groovy 컴파일러에 의해 동적으로 바이트코드로 컴파일됨

----------------------------------------------

런타임

JUnit Test Runner 실행
JVM이 Groovy 컴파일러가 생성한 .class 파일을 기반으로 테스트 실행

 

 

 

 

 

728x90
반응형

댓글