Post

real-world프로젝트 Spring 시작하기(3) - AutoTest gitAction적용, 설명

real-world project 구현 과정 카테고리 보기

저번 포스팅때 API구현을 한다고 하였지만, 이미 구현한 상태에서 느끼기엔 언젠가 Git Action을 쓸 거 지금 미리쓰면 좋다고 생각하였다.

이게 선행되어야된다고 생각하고 만약 다시 만든다면 CI구축을 할 것이므로 API구현보다 빠른 순서에 넣었다.

간단한 GitAction에 대해서는 큰 공부 필요없이 도큐읽고 작성하면 된다.

템플릿도 제공하고 있으니.. 참고하자.

먼저 코드를 보면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
name: auto test java

on:
  push:
    branches: [ "master" ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup Java JDK
        uses: actions/setup-java@v3.5.0
        with:
          distribution: 'temurin'
          java-version: '18'
          
      - name: Grant execute permission gradlew
        run: chmod +x gradlew
        
      - name: Build
        run: ./gradlew build -x test
      
      - name: Test
        run: SPRING_PROFILES_ACTIVE=[test] ./gradlew test
      
      - name: Publish Test Results
        uses: EnricoMi/publish-unit-test-result-action@v2
        if: always()
        with:
          junit_files: "build/test-results/test/**/*.xml"

위에서 부터 하나씩 공부해보았다.

  • name : 작성하지 않아도 된다. 이 전체 흐름인 워크플로우의 이름이다. 공식문서에 따르면 작성을 하지 않으면 root기준의 파일경로가 워크플로우의 이름이 된다고 한다. 작성시에는

  • on:push:branches : 워크플로우가 작동하는 이벤트를 정의하는 구문이다. on이 달려있으면 그 뒤에는 트리거 역할을 한다. 뒤에 있는 pushbranches는 트리거를 작동시키는 조건인 것이다. 위의 코드에서는 마스터 브런치가, push했을때 이 트리거를 작동시키게 설정해놨다.

  • jobs : workflow가 작동시킬 일들을 정의한다. 따로 지정하지 않으면 병렬적으로 수행된다고 한다. 해당 프로젝트에서는 여러 job을 지정하지 않을것이므로 알아만 두었다.

  • build : build는 문법이 아니다. 보통 당연하게 jobs:build:~로 해놔서 여기까지 문법인줄 알았는데 그게 아니고 job의 unique한 이름이다. 즉, build라는 이름을 지정해준것. 그래서 build라고 지정하지 않고 realworld_test로 지정해보았다. 느낌이 확 온다.

  • runs-on : 간단하게 구동될 환경을 설정한다. 윈도우, 맥환경도 가능하다. 보통 리눅스환경에서 돌리므로 ubuntu-latest로 지정하였다.

  • steps : 앞으로 지정해줄 연속적인 task들을 말한다. run이라는 명령어를 통해 task들을 만들 수 있다. 모든 run들이 동작하지 않을 수 있지만, 모든 run들은 steps안에서 실행되어야 한다. 당장 위의 코드만 봐도 run이 없는 steps들이 있다.

  • uses : 공용 레퍼지토리, 공개된 다른 사람들의 작업단위를 가져다 실행시킬 수 있게 한다. {소유자}/{저장소명}@{참조자} 등의 문법으로 사용할 수 있다. 위의 경우
    1
    2
    
    uses: actions/checkout@v3
    uses: EnricoMi/publish-unit-test-result-action@v2
    

    이렇게 쓰인 두개를 보면, 소유자는 action, EnricoMi이고 저장소명은 checkoutpublish-unit-test-result-action으로 확인할 수 있다. 또한 참조자는 v3v1인데 배포된 주요 버전명 및 브랜치를 넣을 수 있다. 그래서 실제로 https://github.com/EnricoMi/publish-unit-test-result-action에 접근하면 저 레포지토리를 확인할 수 있다.

  • with : with은 위의 uses를 사용할 때 필요한 인풋값들을 설정할 수 있게 한다. 위의 코드에서
1
2
3
with:
    distribution: 'temurin'
    java-version: '18'

의 의미는 저바 버전을 18로 맞추고 Eclipse Temurin저장소에서 jdk를 받아올 것을 알려주는 것이다.

☝️ETC

이제 남은 구문들에 대한 간단한 해석을 해볼 것이다.

1
run: SPRING_PROFILES_ACTIVE=[test] ./gradlew test

는 왜 작성하였나면, 이를 작성하지 않는다면 Spring Test를 Github에서 실행할 때 DataBase Connect을 찾지 못해서 에러가 뜬다.

왜지? profile이 뭔데? 이를 이해하기 위해서 스프링 부트 공식 문서를 살펴보았다. https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.profiles

?? 무슨 test환경을 분리한다는데..그럴려면 test파일을 작성해야한다고 했다. 근데 난 test파일을 작성한 적이 없다.

1
spring.profiles.active=test

이런 구문을 짜야한다는데 나는 이런 구문을 작성한 적이 없다. 근데 된다?

그래서 코드를 지워보고 다시 action을 돌려봤다.

잘 된다?

생각해보았다. 왜 이 코드가 필요 없었는지

처음에 커넥션 즉, 데이터베이스 관련 설정을 못찾아서 테스트가 오류가 났다.

그래서 tests폴더안에 appliation.properties를 작성하여 데이터베이스 관련 설정을 삽입하였다.

1
2
3
4
5
6
7
8
9
10
11
# H2
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.format_sql=true
spring.jpq.show-sql=true

#secret

real-world.token.expiry=3000000
real-world.token.key=realworldPostGreSQL0132474654564564213131d31vfxvjfijkjdks

그리고 gitAction에 spring boot Profile 관련 코드를 넣었다.

그랬더니 되었다.

즉, 이미 appplication.properties를 작성한 시점부터 되는거였다.

깃 액션을 작성할 당시 https://jane514.tistory.com/4이 블로그를 참조하여 작성하였는데, 무분별하게 작성하니까 불필요한 코드를 삽입하게 된 것이다.

아직 공부가 더 필요하겠지만 그렇다.

때문에 바뀐 코드는

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
name: auto test java

on:
  push:
    branches: [ "master" ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup Java JDK
        uses: actions/setup-java@v3.5.0
        with:
          distribution: 'temurin'
          java-version: '18'
          
      - name: Grant execute permission gradlew
        run: chmod +x gradlew
        
      - name: Build
        run: ./gradlew build -x test
      
      - name: Test
      #  run: SPRING_PROFILES_ACTIVE=[test] ./gradlew test
        run: ./gradlew test
      
      - name: Publish Test Results
        uses: EnricoMi/publish-unit-test-result-action@v2
        if: always()
        with:
          junit_files: "build/test-results/test/**/*.xml"

가 될 것이다.

다음 구문은 이것이다.

1
2
3
4
5
- name: Publish Test Results
  uses: EnricoMi/publish-unit-test-result-action@v2
  if: always()
  with:
    junit_files: "build/test-results/test/**/*.xml"

이 구문인데, 이는 저기 명시된 저장소에 문법이 설명되어 있다.

if: alway() : 이 구문은 앞의 steps들에서 실패가 나도 무조건 실행하도록 보장하는 코드라고 한다.

with:junit_files: "build/test-results/test/**/*.xml" : with에 대해서는 위에서 설명했다. 여기서 junit_files:~구문은 junit_files라는 변수를 생성하고 저 값을 넣어서 uses의 인풋에 전달한다는 의미이다.

여기서 설정해줘야할것이 있는데, 뒤에 있는 build~는 실제 사용하는 path여야한다.

내 프로젝트의 경우, junit을 통해 test를 실행하면 build/test-results/test/binary/??.xml에 쌓인다. 이 경로를 적어줘야한다. 설정에 따라 다를것이므로 잘 확인해서 써야한다.

만약 제대로된 경로를 적지 않았을 경우

처럼 Could not find any files for 본인이 작성한 Path가 뜨고, Test Results에는 아무것도 수행되지 않을 것이다.

더욱 무서운 점은 이 테스트가 ☑️가 뜨며 성공으로 뜬다는 것이다. 그러므로 주의가 필요하다.

Next

다음은 User Singup관련 서비스들을 작성해볼 것이다.

Reference

현재 이 프로젝트는 vue.js + vite + vuex + Spring boot, Spring Data JPA + Spring Security 를 이용하여 real-world 데모버전을 제작완료하였습니다. https://github.com/kkminseok/real-world-springboot

This post is licensed under CC BY 4.0 by the author.