코딩하는 털보

STUDY HALLE - 4주차 추가 과제(1) 본문

Diary/Study Halle

STUDY HALLE - 4주차 추가 과제(1)

이정인 2020. 12. 23. 02:03

과제 0. JUnit 5 학습하세요.

  • 인텔리J, 이클립스, VS Code에서 JUnit 5로 테스트 코드 작성하는 방법에 익숙해 질 것.
  • 이미 JUnit 알고 계신분들은 다른 것 아무거나!
  • 더 자바, 테스트 강의도 있으니 참고하세요~

과제 1. live-study 대시 보드를 만드는 코드를 작성하세요.

  • 깃헙 이슈 1번부터 18번까지 댓글을 순회하며 댓글을 남긴 사용자를 체크 할 것.
  • 참여율을 계산하세요. 총 18회에 중에 몇 %를 참여했는지 소숫점 두자리가지 보여줄 것.
  • Github 자바 라이브러리를 사용하면 편리합니다.
  • 깃헙 API를 익명으로 호출하는데 제한이 있기 때문에 본인의 깃헙 프로젝트에 이슈를 만들고 테스트를 하시면 더 자주 테스트할 수 있습니다.

JUnit5 학습

JUnit은 자바 프로그래밍 언어용 단위 테스트 프레임워크이며, 자바 TDD(테스트 주도 개발)의 핵심적인 역할을 한다.

현재는 JUnit 5까지 등장하였으며, Spring Boot 2.2.x 부터 기본적으로 JUnit 5를 채택하고 있다.

JUnit 5

  • JUnit 4에서는 단일 jar가 모든 기능을 수행했던 것에 비하여, JUnit 5는 세가지 서브 프로젝트로 구성되어 있다.
    • JUnit Platform : JVM에서 테스트 프레임 워크를 시작하기위한 기반이며 TestEngine 인터페이스를 정의하여 테스트를 실행한다. 또한 빌드 툴이나 IDE와 관계된 모듈을 제공한다.
    • JUnit Jupiter : 테스트 작성을 위한 프로그램과 확장 기능의 집합이며 JUnit 5테스트를 실행하기 위한 TestEngine(Jupiter Engine)을 제공한다.
    • JUnit Vintage : 과거 JUnit 버전을 실행하기 위한 TestEngine(Vintage Engine)을 제공한다.
  • 자바 8 또는 그 이상 버전을 요구한다.

img

사진 출처 : https://www.swtestacademy.com/junit-5-architecture/

의존성 설정

    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.7.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.7.0</version>
        <scope>test</scope>
    </dependency>

테스트 작성하기

  • JUnit 5 어노테이션
어노테이션 설명
@Test 메서드가 테스트 메서드임을 나타낸다.
@BeforeAll 해당 메서드가 현재 클래스의 모든 테스트 메서드보다 이후에 실행된다.
@BeforeEach 해당 메서드가 각 테스트 메서드가 실행되기 전에 실행된다.
@AfterAll 해당 메서드가 현재 클래스의 모든 테스트 메서드보다 먼저 실행된다.
@AfterEach 해당 메서드가 각 테스트 메서드가 실행된 후에 실행된다.
@DisplayName 테스트 클래스 또는 테스트 메서드의 이름을 정의할 수 있다.
@Disable 테스트 클래스 또는 테스트 메서드를 비활성화 한다.
@Order 메서드 또는 필드의 순서를 정할 때 사용한다.
@RepeatedTest 지정된 횟수만큼 반복하는 테스트 템플릿 메서드임을 나타낸다.
@Tag 테스트 클래스 또는 테스트 메서드에 태그를 설정한다. 태그는 빌드 툴에서 사용할 수 있다.
@TestFactory 메서드가 동적 테스트를 위한 테스트 팩토리 메서드임을 나타낸다.
@TestInstance 테스트 클래스에 대해 테스트 인스턴스 라이프사이클을 구성하는 데 사용됩니다 .
@TestMethodOrder 테스트 클래스에 대해 테스트 메서드 실행 순서를 구성하는 데 사용됩니다 .
@TestTemplate 메서드가 테스트 템플릿 메서드임을 나타낸다. (호출용)
@Timeout 테스트 클래스 또는 테스트 메서드에 대한 시간 초과를 설정한다.
  • 테스트할 클래스 예제
public class Calculator {

    public static int add(int num1, int num2) {
        return num1 + num2;
    }

    public static int sub(int num1, int num2) {
        return num1 - num2;
    }

    public static int mul(int num1, int num2) {
        return num1 * num2;
    }

    public static int div(int num1, int num2) {
        if ( num2 == 0 ) {
            throw new RuntimeException("0으로 나눌 수 없습니다.");
        }
        return num1 / num2;
    }

    public static boolean bigger(int num1, int num2) {
        return num1 > num2;
    }

}
  • 테스트
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {

    @BeforeAll
    public static void testSign() {
        System.out.println("=== test start ===");
    }

    @Test
    @DisplayName("계산 테스트")
    public void calculateTest() {
        //assertTrue()
        assertTrue(Calculator.bigger(10, 2));

        //assertEquals()
        int sum = Calculator.add(10, 2);
        assertEquals(12, sum);

        //assertThat()
        assertThat(Calculator.add(10, 2)).isEqualTo(12);
        assertThat(Calculator.sub(10, 2)).isEqualTo(8);
        assertThat(Calculator.mul(10, 2)).isEqualTo(20);
        assertThat(Calculator.div(10, 2)).isEqualTo(5);

        //assertAll(), assertion의 그룹화.
        //그룹화를 하지 않은 경우 중간에 실패하면 다음 테스트를 진행하지 않지만,
        //그룹화를 하면 중간에 실패하더라도 그룹 내 모든 테스트가 실행된다.
        assertAll(
                () -> assertThat(Calculator.add(10, 2)).isEqualTo(12),
                () -> assertThat(Calculator.sub(10, 2)).isEqualTo(8),
                () -> assertThat(Calculator.mul(10, 2)).isEqualTo(20),
                () -> assertThat(Calculator.div(10, 2)).isEqualTo(5)
        );

        //assertThrows(), 예외 확인
        assertThrows(RuntimeException.class, () -> Calculator.div(10,0));
    }
}

참고 자료 :

https://www.swtestacademy.com/junit-5-architecture/

https://junit.org/junit5/docs/current/user-guide/#overview

https://ko.wikipedia.org/wiki/JUnit

https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/package-summary.html


live-study 참여율 계산하기

GitHub for Java 라이브러리 추가

        <dependency>
            <groupId>org.kohsuke</groupId>
            <artifactId>github-api</artifactId>
            <version>1.116</version>
        </dependency>

참여율 클래스 구현

public class Attendance {

    private GitHub gitHub;
    private GHRepository ghRepository;
    public HashMap<String, Integer> attendanceMap = new HashMap<>();

    public Attendance() throws Exception {
        gitHub = new GitHubBuilder().withOAuthToken(myToken).build();
        ghRepository = gitHub.getRepository("rockintuna/live-study").getSource();
        System.out.println("Attendance Object Created");
    }

    public void calcRate() throws IOException {
        System.out.println("begin calc");
        List<GHIssue> issues = ghRepository.getIssues(GHIssueState.ALL);

        for ( GHIssue issue : issues ) {
            List<GHIssueComment> comments = issue.getComments();

            for (GHIssueComment comment : comments) {
                String username = comment.getUser().getLogin();

                if ( username == null ) {
                } else if ( attendanceMap.containsKey(username) ) {
                    Integer count = attendanceMap.get(username);
                    attendanceMap.replace(username, ++count);
                } else {
                    attendanceMap.put(username, 1);
                }
            }
        }
    }

    public void show() throws IOException {
        System.out.println("beign show");
        float total = ghRepository.getIssues(GHIssueState.ALL).size();    
        Set<String> userList = attendanceMap.keySet();

        for (String username : userList) {
            String attendanceRate = String.format("%.2f", attendanceMap.get(username)*100/total);
            System.out.println(username+" "+attendanceRate);
        }
    }
}

기능은 동작하지만... calcRate 메서드에서 한참 동안 계산하는 문제가 있다.

성능적 개선이 필요할 듯 하다.

테스트

class AttendanceApplicationTests {

    @Test
    public void test() throws Exception {
        Attendance attendance = new Attendance();
        attendance.calcRate();
        attendance.show();

          //현재 나의 제출한 과제 3개..와 총 이슈 18개로 결과를 테스트
        float myRate = 3*100/18f;
        assertThat(attendance.attendanceMap.get("rockintuna")*100/attendance.total).isEqualTo(myRate);
    }
}

Output

Attendance Object Created
begin calc
beign show
kimzerovirus 5.56
sojintjdals 22.22
jessi68 11.11
HyangKeunChoi 33.33
phantom08266 5.56
twowinsh87 22.22
ohhhmycode 27.78
ufonetcom 33.33
sigriswil 16.67
ssonsh 38.89
dsunni 5.56
catsbi 22.22
rockintuna 16.67
eomgr55 5.56
Azderica 5.56
jymaeng95 38.89
ggomjae 5.56
fpdjsns 33.33
binghe819 16.67
seovalue 16.67
kys4548 27.78
Wordbe 5.56
boraborason 33.33
Resilient923 22.22
KyungJae-Jang 27.78
hojunnnnn 33.33
kongduboo 38.89
ahyz0569 27.78
shin-ga-eun 11.11
GetMapping 16.67
herohe910623 5.56
hyngsk 5.56
lee82762 16.67
DevJiho 5.56
glowing713 11.11
loop-study 27.78
G-ONL 5.56
yskkkkkk 27.78
SJ-dev-io 5.56
dkyou7 5.56
jaxx2001 22.22
idiot2222 33.33
metorg 16.67
limyeonsoo 33.33
Youngerjesus 38.89
gcha-kim 38.89
numuduwer 33.33
pej4303 33.33
noah-standard 11.11
JuHyun419 5.56
zhaoSeo 16.67
cellenar26 16.67
thisisyoungbin 38.89
kyu9 33.33
jongnan 33.33
star1606 11.11
kimdm1994 5.56
nimkoes 33.33
Ryureka 22.22
jaeyeon93 11.11
Lee-jaeyong 5.56
plzprayme 33.33
Rebwon 22.22
sky7th 27.78
YuSeungmo 27.78
ejxzhn22 22.22
sskim91 33.33
minzzang 5.56
younwony 16.67
kgc0120 22.22
yhxkit 11.11
jaeeunis 16.67
DDOEUN 33.33
haeinoh 16.67
chulphan 16.67
awesomeo184 5.56
whiteship 72.22
miseongshin 5.56
jjone36 27.78
CODEMCD 33.33
roeniss 33.33
ksj0109188 5.56
hyenny 5.56
yks095 5.56
yoojaeseon1 5.56
sowjd 22.22
SJParkkk 16.67
chaechae0322 16.67
LeeGiCheol 11.11
angelatto 5.56
surfing2003 11.11
9bini 11.11
1031nice 33.33
TaeYing 5.56
dionidip 5.56
JadenKim940105 33.33
sunho-lee 11.11
SooJungDev 33.33
dacapolife87 33.33
Youngjin-KimY 27.78
cs7998 11.11
ChoiGiSung 38.89
wideo2 16.67
manOfBackend 16.67
yallyyally 5.56
monkeyDugi 11.11
JJongSue 16.67
jiwoo-choi 33.33
sangw0804 5.56
Hongyeongjune 22.22
bingbingpa 22.22
reinf92 27.78
honux77 33.33
accidentlywoo 22.22
rshak8912 33.33
uHan2 22.22
ghYoon93 5.56
dip0cean 11.11
dmstjd1024 33.33
tjdqls1200 5.56
cold-pumpkin 11.11
asqwklop12 38.89
Junhan0037 33.33
zilzu4165 5.56
jaehyunup 16.67
d-h-k 11.11
HyeonWuJeon 22.22
hypernova1 27.78
dev-jaekkim 33.33
delusidiot 16.67
Park-Youngwoo 11.11
ZhenxiKim 5.56
abcdsds 27.78
dudqls5271 16.67
k8440009 5.56
jongyeans 33.33
hong918kr 16.67
tbnsok40 27.78
LeeJeongSeok 16.67
id6827 5.56
WonYong-Jang 27.78
sjhello 11.11
addadda15 16.67
JsKim4 16.67
Ahnyezi 16.67
ku-kim 22.22
sowhat9293 16.67
gmldnjs26 5.56
hoi-hoon 5.56
yangseungin 16.67
ldw1220 5.56
sangwoobae 38.89
cocodori 16.67
inhalin 27.78
kiss9815 5.56
keunyop 27.78
jigmini 33.33
kwj1270 16.67
hanull 16.67
ByungJun25 38.89
Dubidubab 11.11
DevelopJKong 33.33
bperhaps 5.56
hongminpark 33.33
lleezz 5.56
twosoull 5.56
haemin-jeong 33.33
2yeseul 27.78
seoulstationlounge 5.56
DevRyu 16.67
goodzzong 5.56
ohsg0226 5.56
daroguzo 5.56
JOYB28 11.11
perm4 11.11
kingsubin 33.33
YeseulDo 33.33
372dev 22.22
lee-maru 27.78
sophysophysophysophy 27.78
kyunyan 5.56
mimdong0917 5.56
gintire 22.22
LeeWoooo 33.33
good-influence 33.33
elon09 22.22
yky03 33.33
GunnwooKim 22.22
jwsims1995 22.22
dongyeon94 27.78
yongtaelim 16.67
EdwardJae 5.56
m3252 16.67
wdEffort 16.67
hwonny 5.56
myBabyGrand 16.67
rlatmd0829 38.89
kjw217 38.89
HanJaehee 22.22
eatnows 22.22
tocgic 27.78
msmn1729 27.78
sweetchinmusic 16.67
0417taehyun 16.67
batboy118 5.56
JUNGHOJONG 5.56
riyenas0925 5.56
ehdrhelr 27.78
osk2090 27.78
jeeneee 33.33
MoonHKLee 38.89
githubjam2 33.33
Lob-dev 38.89
gurumee92 22.22
devShLee7017 33.33
UJ15 5.56
resister12 5.56
geneaky 27.78
ysmiler 33.33
soongjamm 22.22
parksil0 22.22
devksh930 27.78
sellester 5.56
ssayebee 5.56
hyeonic 33.33
castleCircle 27.78
youngsunshin94 11.11
KilJaeeun 38.89
ksundong 33.33
Yadon079 38.89
kimmy100b 5.56
jaewon0913 11.11
yunieom 22.22
9m1i9n1 27.78
JeongJin984 27.78
etff 38.89
devvip 27.78
koreas9408 16.67
junhok82 5.56
damho1104 38.89
kksb0831 16.67
heonjun91 27.78
sinchang1 27.78
Livenow14 5.56
league3236 27.78
ShimSeoungChul 27.78
Gomding 27.78
Jul-liet 33.33
gtpe 38.89
ParkIlHoon 27.78
Chohongjae 38.89
ohjoohyung 22.22
lee-jemu 11.11
sungpillhong 33.33
anna9001 5.56
sujl95 33.33
Parkyunhwan 22.22
KJJ924 16.67
kdm8939 5.56
kopokero 5.56
minikuma 16.67
fkfkfk9 27.78
doyoung0205 33.33
DonggeonHa 5.56
kyung-Ho-sin 5.56
sunnynote 33.33
Jangilkyu 33.33
nhs0912 5.56
pka0220z 33.33
redbean88 22.22
JungHyeokMoon 16.67
rudus1012 5.56
shjang1013 5.56
conyconydev 33.33
pond1029 33.33
yeGenieee 33.33
garlickim 33.33
ykob501 5.56
Kim-JunHyeong 11.11
SeungWoo-Oh 38.89
jikimee64 33.33
JoongSeokD 27.78
mongzza 38.89
nekisse-lee 5.56
highright96 11.11
s0w0s 33.33
iseunghan 33.33
mokaim 16.67
chaejunlee 27.78
kimseungki94 11.11
GGob2 27.78
RealSong88 5.56
ghwann 5.56
sejongdeveloper 33.33
Yo0oN 27.78
oktopman 16.67
rowanlee92 11.11
kdh9428 5.56
clap1030 5.56
giyeon95 27.78
yeo311 22.22
miok-jung 16.67
gblee87 27.78
coldhoon 11.11
Sungjun-HQ 33.33
memoregoing 27.78
HwangWonGyu 5.56
binaryyoung 5.56
Jason-time 33.33
BaeJi77 22.22
choiyoungkwon12 16.67
mkkim90 11.11
JoosJuliet 22.22

참고자료 :

https://github-api.kohsuke.org/

https://github-api.kohsuke.org/apidocs/org/kohsuke/github/GHRepository.html

https://docs.github.com/en/free-pro-team@latest/rest/reference/repos

Comments