source code: https://github.com/kgmhk/spring-boot-tutorial/tree/gradlew

gradlew (gradle wrapper) 란

  • gradle wrapper 줄여서 gradlew 는 새로운 환경에서 프로젝트를 설정할 때 java나 gradle을 설치하지 않고 바로 빌드할 수 있게 해주는 역할을 한다.
  • gradlew 를 생성하면 아래와 같은 파일들이 생성된다. (참고 : https://docs.gradle.org/current/userguide/gradle_wrapper.html)
.
├── build.gradle
├── settings.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
  • gradlew 는 shell script 이며 gradlew.bat는 Window batch script 이다.
  • gradlew 를 사용하는 가장 큰 이유는 아래와 같이 로컬환경에서 빌드할 경우 로컬 환경에 설치된 java와 gradle 버전에 영향을 받게 된다.
$ gradle build
  • gradlew 를 이용하여 빌드하면 로컬 환경 java와 gradle 버전과 상관없이 새로운 프로젝트를 빌드할 수 있다.
$ ./gradlew build

 

gradlew 생성하기

  • 프로젝트 초기에 gradlew 생성 시 아래 명령어를 이용하여 gradlew 생성
$ gradle init
  • 이미 로컬 환경에서 build.gradle 를 사용하여 빌드를 진행하고 있던 프로젝트라면 아래 명령어로 gradlew 생성
$ gradle wrapper
> Task :wrapper

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

 

gradlew 를 이용한 빌드

  • gradlew 빌드
$ ./gradlew build
  • gradlew 빌드 후 기존 어플리케이션 실행
$ ./gradlew build && java -jar build/libs/helloworld-0.1.0.jar

BUILD SUCCESSFUL in 1s
4 actionable tasks: 4 up-to-date

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.6.RELEASE)

2019-08-02 09:40:27.901  INFO 54669 --- [           main] hello.Application                        : Starting Application on apseonote344.ad.ea.com with PID 54669 (/Users/gkwak/Documents/spring/helloworld/build/libs/helloworld-0.1.0.jar started by gkwak in /Users/gkwak/Documents/spring/helloworld)
2019-08-02 09:40:27.904  INFO 54669 --- [           main] hello.Application                        : No active profile set, falling back to default profiles: default
2019-08-02 09:40:28.927  INFO 54669 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-08-02 09:40:28.957  INFO 54669 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-08-02 09:40:28.957  INFO 54669 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.21]
2019-08-02 09:40:29.046  INFO 54669 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-08-02 09:40:29.046  INFO 54669 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1092 ms
2019-08-02 09:40:29.241  INFO 54669 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-08-02 09:40:29.447  INFO 54669 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-08-02 09:40:29.452  INFO 54669 --- [           main] hello.Application                        : Started Application in 1.956 seconds (JVM running for 2.353)

 

 

Posted by 사용자 guru_k

댓글을 달아 주세요

Set a new git repository

Git 2019. 8. 1. 16:02

1. git init

$ git init

2. git add <files>

$ git add .

3. git commit

$ git commit -m 'first commit'

4. Create a new git repository

5. Add remote & Push 

$ git remote add origin https://github.com/username/repo
$ git push -u origin master

6. Check it out on your repository.

Posted by 사용자 guru_k

댓글을 달아 주세요

[Git] Add git branch

Git 2019. 8. 1. 15:55

Add git remote branch

git push -u origin <branch name>

Add git local branch

$ git branch <branch name>
Posted by 사용자 guru_k

댓글을 달아 주세요

[Git] Delete git branch

Git 2019. 8. 1. 15:54

Delete git remote branch

$ git push --delete origin <branch name>

Delete git local branch

$ git branch -d <branch name>
$ git branch -D <branch name>

 

Posted by 사용자 guru_k

댓글을 달아 주세요

using below command

fatal: refusing to merge unrelated histories
Posted by 사용자 guru_k
TAG git, Pull, Push

댓글을 달아 주세요

source code:  https://github.com/kgmhk/spring-boot-tutorial/tree/unit-test

1. build.gradle 파일에 testCompile 추가

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.6.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

bootJar {
    baseName = 'helloworld'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("org.springframework.boot:spring-boot-starter-test")  // test complie 추가
}

 

2. test case 추가

  • "/" , "/hello" endpoint 에 대한 test case 추가
src/test/java/hello/HelloControllerTest.java
package hello;

import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {

    @Autowired
    private MockMvc mvc;

    @Test
    public void indexTest() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))   // "/" 에 대한 request 요청
                .andExpect(status().isOk())                                               // response 가 200 ok 일때
                .andExpect(content().string(equalTo("Greetings from Spring Boot!")));     // response로 받은 데이터가 같은지 확인
    }

    @Test
    public void helloTest() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON))   // "/hello" 에 대한 request 요청
                .andExpect(status().isOk())                                                    // response 가 200 ok 일때
                .andExpect(content().string(equalTo("Hello world")));                          // response로 받은 데이터가 같은지 확인
    }
}
  • integration test 추가
src/test/java/hello/HelloControllerIT.java
package hello;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;

import java.net.URL;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerIT {

    @LocalServerPort
    private int port;

    private URL base;

    @Autowired
    private TestRestTemplate template;

    @Before
    public void setUp() throws Exception {
        this.base = new URL("http://localhost:" + port + "/");
    }

    @Test
    public void indexTest() throws Exception {
        ResponseEntity<String> response = template.getForEntity(base.toString(),
                String.class);
        assertThat(response.getBody(), equalTo("Greetings from Spring Boot!"));
        
    }

    @Test
    public void helloTest() throws Exception {
        ResponseEntity<String> response = template.getForEntity(base.toString() + "hello",
                String.class);
        assertThat(response.getBody(), equalTo("Hello world"));
        
    }
}

 

3. unit test run

  • unit test 성공 시
$ gradle test

> Task :test
2019-08-01 15:28:09.933  INFO 98766 --- [       Thread-5] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
2019-08-01 15:28:09.933  INFO 98766 --- [       Thread-8] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
  • unit test 실패 시
$ gradle test

> Task :test

hello.HelloControllerTest > helloTest FAILED
    java.lang.AssertionError at HelloControllerTest.java:36
2019-08-01 15:30:51.739  INFO 99045 --- [       Thread-5] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
2019-08-01 15:30:51.739  INFO 99045 --- [       Thread-8] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

4 tests completed, 1 failed

> Task :test FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at: file:///Users/gkwak/Documents/spring/helloworld/build/reports/tests/test/index.html

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 5s
3 actionable tasks: 2 executed, 1 up-to-date

4. ETC

  • unit test 실패 시 `gradle test --debug`나 `gradle test --info` 를 사용하면 좀더 자세한 로그를 볼 수 있다. 하지만 --bebug나 --info를 사용 시 너무 많은 로그가 출력되므로 gradle.build에 아래 testLogging 의 exceptionFormat 을 'full'로 설정하면 적절하게 볼 수 있다.
  • 아래에 예를 통해 알아보자.
  • gradle.build에  아래 항목을 추가
test {
    testLogging {
        exceptionFormat = 'full'
    }
}
  • HelloControllerTest.java 에서 테스트 항목 중 하나를 실패하도록 수정
@Test
public void helloTest() throws Exception {
	mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON))
	.andExpect(status().isOk())                                                    
	.andExpect(content().string(equalTo("it will cause failure")));  // response는 "Hello world" 이나 테스트는 "it will cause fail" 이므로 이 테스트는 실패하게된다.
}
  • 이후 다시 unit test를 진행하면 실제 retrun 되는 response와 다른점이 아래와 같이 로그에 출력된다.
$ gradle test

> Task :test

// 아래와 같이 response와 expected가 다를 경우 해당 내용이 출력

hello.HelloControllerTest > helloTest FAILED
    java.lang.AssertionError: Response content
    Expected: "it will cause fail"
         but: was "Hello world"
        at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
        at org.springframework.test.web.servlet.result.ContentResultMatchers.lambda$string$3(ContentResultMatchers.java:130)
        at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:195)
        at hello.HelloControllerTest.helloTest(HelloControllerTest.java:36)
2019-08-01 15:39:04.475  INFO 99780 --- [       Thread-8] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
2019-08-01 15:39:04.475  INFO 99780 --- [       Thread-5] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

4 tests completed, 1 failed

> Task :test FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at: file:///Users/gkwak/Documents/spring/helloworld/build/reports/tests/test/index.html

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 4s
3 actionable tasks: 2 executed, 1 up-to-date

 

Posted by 사용자 guru_k

댓글을 달아 주세요