๐Ÿ˜€
fistkim TECH BLOG
  • Intro
  • ๊ฐ•์˜
    • Reactive Programming in Modern Java using Project Reactor
      • Reactor execution model 1
      • Reactor execution model 2
      • Reactor execution model 3 - parallelism
      • Reactor execution model 4 - overview
      • Transform
      • Combine
      • Side Effect Methods
      • Exception/Error handling
      • retry, retryWhen, repeat
      • BackPressure
      • Cold & Hot Streams
    • NEXTSTEP ํด๋ฆฐ์ฝ”๋“œ with java 9๊ธฐ
      • ์ •๋ฆฌ๋…ธํŠธ
    • NEXTSTEP DDD ์„ธ๋ ˆ๋‚˜๋ฐ 2๊ธฐ
      • CH01 ๋„๋ฉ”์ธ ์ฃผ๋„ ์„ค๊ณ„ ์ดํ•ด
      • CH02 ํฌ๊ฒŒ ์†Œ๋ฆฌ ๋‚ด์–ด ๋ชจ๋ธ๋ง ํ•˜๊ธฐ
      • CH03 ๋„๋ฉ”์ธ ์ฃผ๋„ ์„ค๊ณ„ ๊ธฐ๋ณธ ์š”์†Œ
      • CH04 ๋„๋ฉ”์ธ ์ฃผ๋„ ์„ค๊ณ„ ์•„ํ‚คํ…์ฒ˜
      • CH05 ๋„๋ฉ”์ธ ์ด๋ฒคํŠธ
    • NEXTSTEP ์ธํ”„๋ผ ๊ณต๋ฐฉ 1๊ธฐ
      • ๋ง ๋ถ„๋ฆฌํ•˜๊ธฐ
      • ํ†ต์‹  ํ™•์ธํ•˜๊ธฐ
      • ๋„์ปค ์ปจํ…Œ์ด๋„ˆ ์ดํ•ดํ•˜๊ธฐ
      • [๋ฏธ์…˜ 1] ์„œ๋น„์Šค ๊ตฌ์„ฑํ•˜๊ธฐ ์‹ค์Šต
      • [๋ฏธ์…˜ 2] ์„œ๋น„์Šค ๋ฐฐํฌํ•˜๊ธฐ ์‹ค์Šต
      • ์„œ๋ฒ„ ์ง„๋‹จํ•˜๊ธฐ
      • ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ง„๋‹จํ•˜๊ธฐ
      • [๋ฏธ์…˜ 3] ์„œ๋น„์Šค ์šด์˜ํ•˜๊ธฐ
      • ์›น ์„ฑ๋Šฅ ์ง„๋‹จํ•˜๊ธฐ
      • ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ
      • k6
      • [๋ฏธ์…˜ 4] ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ
      • ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ๊ฐœ์„ ํ•˜๊ธฐ
      • ์บ์‹ฑ ํ™œ์šฉํ•˜๊ธฐ
      • [๋ฏธ์…˜ 5] ํ™”๋ฉด ์‘๋‹ต ๊ฐœ์„ ํ•˜๊ธฐ
      • Redis Annotation ๋ฐ ์„ค์ •
      • ์ธ๋ฑ์Šค ์ดํ•ดํ•˜๊ธฐ & DB ํŠœ๋‹
      • [๋ฏธ์…˜ 6-1] ์กฐํšŒ ์„ฑ๋Šฅ ๊ฐœ์„ ํ•˜๊ธฐ
      • [๋ฏธ์…˜ 6-2] DB ์ด์ค‘ํ™” ์ ์šฉ
    • NEXTSTEP ๋งŒ๋“ค๋ฉด์„œ ๋ฐฐ์šฐ๋Š” Spring 3๊ธฐ
      • CH01 ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉํ–ฅ ๋ฐ”๋ผ๋ณด๊ธฐ
      • CH02 HTTP ์ดํ•ด - ์›น ์„œ๋ฒ„ ๊ตฌํ˜„
        • HTTP ํŒŒ์‹ฑ
        • HTTP ์›น ์„œ๋ฒ„ ๊ตฌํ˜„
      • CH03 MVC - @MVC ํ”„๋ ˆ์ž„์›Œํฌ ๊ตฌํ˜„
        • Servlet ๋‹ค์‹œ ์งš๊ธฐ
        • Cookie, Session ๋‹ค์‹œ ์งš๊ธฐ
        • MVC ํ”„๋ ˆ์ž„์›Œํฌ ๊ตฌํ˜„
      • CH04 ๋‚˜๋งŒ์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ตฌํ˜„
      • CH05 DI - DI ํ”„๋ ˆ์ž„์›Œํฌ ๊ตฌํ˜„
      • CH06 Aspect OP
    • ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ
      • ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์•„ํ‚คํ…์ฒ˜
      • WebAsyncManagerIntegrationFilter
      • SecurityContextPersistenceFilter
      • HeaderWriterFilter
      • CsrfFilter
      • (+) ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ + JWT
      • (+) ๋งˆ์น˜๋ฉฐ
    • ๋” ์ž๋ฐ”, ์ฝ”๋“œ๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•
      • CH01 JVM ์ดํ•ดํ•˜๊ธฐ
      • (+) ํด๋ž˜์Šค ๋กœ๋” ์ดํ•ดํ•˜๊ธฐ
      • CH02 ๋ฐ”์ดํŠธ ์ฝ”๋“œ ๋ถ„์„ ๋ฐ ์กฐ์ž‘
      • (+) jacoco
      • CH03 ๋ฆฌํ”Œ๋ ‰์…˜
      • CH04 ๋‹ค์ด๋‚˜๋ฏน ํ”„๋ก์‹œ
      • CH05 ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ
    • ๋” ์ž๋ฐ”, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•
      • CH01 JUnit 5
      • CH02 Mockito
      • (+) Spy vs Mock
      • CH03 ๋„์ปค์™€ ํ…Œ์ŠคํŠธ
      • CH04 ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ
      • (+) VisualVM
      • (+) ํ…Œ์ŠคํŠธ ์ž๋™ํ™”
      • CH05 ์šด์˜ ์ด์Šˆ ํ…Œ์ŠคํŠธ
      • CH06 ์•„ํ‚คํ…์ฒ˜ ํ…Œ์ŠคํŠธ
    • ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ HTTP ์›น ๊ธฐ๋ณธ ์ง€์‹
      • CH01 ์ธํ„ฐ๋„ท ๋„คํŠธ์›Œํฌ
      • CH02 HTTP ๊ธฐ๋ณธ
      • CH03 HTTP ๋ฉ”์„œ๋“œ ์†์„ฑ
      • CH04 HTTP ๋ฉ”์„œ๋“œ ํ™œ์šฉ
      • CH05 HTTP ์ƒํƒœ์ฝ”๋“œ
      • CH06 HTTP ํ—ค๋”1 - ์ผ๋ฐ˜ ํ—ค๋”
      • CH07 HTTP ํ—ค๋”2 - ์บ์‹œ์™€ ์กฐ๊ฑด๋ถ€ ์š”์ฒญ
      • (+) HTTPS ์›๋ฆฌ
    • ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ ํ•ต์‹ฌ ๊ธฐ์ˆ 
      • CH01 IOC ์ปจํ…Œ์ด๋„ˆ
      • CH02 AOP
      • (+) ์Šคํ”„๋ง ์˜์กด์„ฑ ๊ด€๋ฆฌ
      • (+) ์ƒ์„ฑ์ž ์ฃผ์ž… ์žฅ์ 
    • ์ฝ”๋”ฉ์œผ๋กœ ํ•™์Šตํ•˜๋Š” GoF์˜ ๋””์ž์ธ ํŒจํ„ด
      • ๊ฐ์ฒด ์ƒ์„ฑ
        • ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด
        • ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ ํŒจํ„ด
        • ์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด
        • ๋นŒ๋” ํŒจํ„ด
        • ํ”„๋กœํ† ํƒ€์ž… ํŒจํ„ด
      • ๊ตฌ์กฐ
        • ์–ด๋Œ‘ํ„ฐ ํŒจํ„ด
        • ๋ธŒ๋ฆฟ์ง€ ํŒจํ„ด
        • ์ปดํฌ์ง“ ํŒจํ„ด
      • ํ–‰๋™
        • (์ž‘์„ฑ์ค‘)
    • ์‹ค์ „ Querydsl
      • CH01 ํ”„๋กœ์ ํŠธ ํ™˜๊ฒฝ๊ตฌ์„ฑ
      • CH02 ์˜ˆ์ œ ๋„๋ฉ”์ธ ๋ชจ๋ธ
      • CH03 ๊ธฐ๋ณธ๋ฌธ๋ฒ•
      • CH04 ์ค‘๊ธ‰ ๋ฌธ๋ฒ•
      • CH05 ์‹ค๋ฌดํ™œ์šฉ (์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA์™€ Querydsl)
      • CH06 ์Šคํ”„๋ง๋ฐ์ดํ„ฐJPA ๊ฐ€ ์ œ๊ณตํ•˜๋Š” Querydsl ๊ธฐ๋Šฅ
      • (+) ๋ณ„์นญ(alias)
      • (+) Slice ์ฟผ๋ฆฌ
    • ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA
      • CH01 ํ•ต์‹ฌ๊ฐœ๋…์ดํ•ด 1
      • CH02 ํ•ต์‹ฌ๊ฐœ๋…์ดํ•ด 2
      • CH03 ํ•ต์‹ฌ๊ฐœ๋…์ดํ•ด 3
      • CH04 Spring Data Common
      • CH05 Spring Data JPA
    • ์‹ค์ „! ์Šคํ”„๋ง ๋ถ€ํŠธ์™€ JPA ํ™œ์šฉ2 - API ๊ฐœ๋ฐœ๊ณผ ์„ฑ๋Šฅ ์ตœ์ ํ™”
      • CH01 ์ง€์—ฐ ๋กœ๋”ฉ๊ณผ ์กฐํšŒ ์„ฑ๋Šฅ ์ตœ์ ํ™”
      • CH02 ์ปฌ๋ ‰์…˜ ์กฐํšŒ ์ตœ์ ํ™”
      • CH03 ์ „์ฒด ์ •๋ฆฌ
    • ์ดˆ๋ณด๋ฅผ ์œ„ํ•œ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์•ˆ๋‚ด์„œ
      • CH01 ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์‹œ์ž‘ํ•˜๊ธฐ
      • CH02 ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์•Œ์•„๋ณด๊ธฐ
      • CH03 ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์‹ค์Šต ์ค€๋น„
      • CH04 ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๊ธฐ๋ณธ ์‹ค์Šต
    • Flutter Provider Essential
      • CH01 Introduction
      • CH02 Provider Overview
      • CH03 TODO App
      • CH04 Weather App
      • CH05 Firebase Authentication App
    • Flutter Bloc Essential
      • CH01 Introduction
      • CH02 Bloc Overview
      • CH03 TODO App
      • CH04 Weather App
      • CH05 Firebase Authentication App
    • Flutter Advanced Course - Clean Architecture With MVVM
      • CH01 Introduction
      • CH02 Clean Architecture 4 Layer
      • CH03 MVVM
      • CH04 Data Layer
      • (+) Data Layer - response to model
      • (+) Data Layer - Network
      • CH05 Domain Layer
      • CH06 Presentation Layer
      • CH07 Application Layer
      • (+) Application Layer - l10n
      • (+) Application Layer - DI
      • (+) Application Layer - environment
    • ์ž๋ฐ” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ž…๋ฌธ
      • CH01 ๋ฌธ์ž์—ด
      • CH02 Array(1, 2 ์ฐจ์› ๋ฐฐ์—ด)
      • CH03 Two pointers, Sliding window[ํšจ์œจ์„ฑ: O(n^2)-->O(n)]
      • CH04 HashMap, TreeSet (ํ•ด์‰ฌ, ์ •๋ ฌ์ง€์› Set)
      • CH05 Stack, Queue(์ž๋ฃŒ๊ตฌ์กฐ)
      • CH06 Sorting and Searching(์ •๋ ฌ, ์ด๋ถ„๊ฒ€์ƒ‰๊ณผ ๊ฒฐ์ •์•Œ๊ณ ๋ฆฌ์ฆ˜)
      • CH07 Recursive, Tree, Graph(DFS, BFS ๊ธฐ์ดˆ)
      • CH08 DFS, BFS ํ™œ์šฉ
      • CH09 Greedy Algorithm
      • CH10 dynamic programming(๋™์ ๊ณ„ํš๋ฒ•)
  • ๋„์„œ
    • ๋งŒ๋“ค๋ฉด์„œ ๋ฐฐ์šฐ๋Š” ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜
      • ํ•™์Šต๋ชฉํ‘œ
      • CH01 ๊ณ„์ธตํ˜• ์•„ํ‚คํ…์ฒ˜์˜ ๋ฌธ์ œ๋Š” ๋ฌด์—‡์ผ๊นŒ?
      • CH02 ์˜์กด์„ฑ ์—ญ์ „ํ•˜๊ธฐ
      • CH03 ์ฝ”๋“œ ๊ตฌ์„ฑํ•˜๊ธฐ
      • CH04 ์œ ์Šค์ผ€์ด์Šค ๊ตฌํ˜„ํ•˜๊ธฐ
      • CH05 ์›น ์–ด๋Œ‘ํ„ฐ ๊ตฌํ˜„ํ•˜๊ธฐ
      • CH06 ์˜์†์„ฑ ์–ด๋Œ‘ํ„ฐ ๊ตฌํ˜„ํ•˜๊ธฐ
      • CH07 ์•„ํ‚คํ…์ฒ˜ ์š”์†Œ ํ…Œ์ŠคํŠธํ•˜๊ธฐ
      • CH08 ๊ฒฝ๊ณ„ ๊ฐ„ ๋งคํ•‘ํ•˜๊ธฐ
      • CH09 ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์กฐ๋ฆฝํ•˜๊ธฐ
      • CH10 ์•„ํ‚คํ…์ฒ˜ ๊ฒฝ๊ณ„ ๊ฐ•์ œํ•˜๊ธฐ
      • CH11 ์˜์‹์ ์œผ๋กœ ์ง€๋ฆ„๊ธธ ์‚ฌ์šฉํ•˜๊ธฐ
      • CH12 ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ ๊ฒฐ์ •ํ•˜๊ธฐ
    • ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜
      • ๋“ค์–ด๊ฐ€๋ฉฐ
      • 1๋ถ€ ์†Œ๊ฐœ
        • 1์žฅ ์„ค๊ณ„์™€ ์•„ํ‚คํ…์ฒ˜๋ž€?
        • 2์žฅ ๋‘ ๊ฐ€์ง€ ๊ฐ€์น˜์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ
      • 2๋ถ€ ๋ฒฝ๋Œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ธฐ: ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„
        • 3์žฅ ํŒจ๋Ÿฌ๋‹ค์ž„ ๊ฐœ์š”
        • 4์žฅ ๊ตฌ์กฐ์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ
        • 5์žฅ ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ
        • 6์žฅ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ
      • 3๋ถ€ ์„ค๊ณ„ ์›์น™
        • 7์žฅ SRP: ๋‹จ์ผ ์ฑ…์ž„ ์›์น™
        • 8์žฅ OCP: ๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™
        • 9์žฅ LSP: ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™
        • 10์žฅ ISP: ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™
        • 11์žฅ DIP: ์˜์กด์„ฑ ์—ญ์ „ ์›์น™
      • 4๋ถ€ ์ปดํฌ๋„ŒํŠธ ์›์น™
        • 12์žฅ ์ปดํฌ๋„ŒํŠธ
        • 13์žฅ ์ปดํฌ๋„ŒํŠธ ์‘์ง‘๋„
        • 14์žฅ ์ปดํฌ๋„ŒํŠธ ๊ฒฐํ•ฉ
      • 5๋ถ€
        • 15์žฅ ์•„ํ‚คํ…์ฒ˜๋ž€?
    • ์Šคํ”„๋ง ์ž…๋ฌธ์„ ์œ„ํ•œ ์ž๋ฐ” ๊ฐ์ฒด ์ง€ํ–ฅ์˜ ์›๋ฆฌ์™€ ์ดํ•ด
      • CH01 ์‚ฌ๋žŒ์„ ์‚ฌ๋ž‘ํ•œ ๊ธฐ์ˆ 
      • CH02 ์ž๋ฐ”์™€ ์ ˆ์ฐจ์ /๊ตฌ์กฐ์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ
      • CH03 ์ž๋ฐ”์™€ ๊ฐ์ฒด ์ง€ํ–ฅ
      • (+) ์ž๋ฐ” ์ฝ”๋“œ ์‹คํ–‰์— ๋”ฐ๋ฅธ ๋ฉ”๋ชจ๋ฆฌ ์ ์žฌ๊ณผ์ •
      • CH04 ์ž๋ฐ”๊ฐ€ ํ™•์žฅํ•œ ๊ฐ์ฒด ์ง€ํ–ฅ
      • CH05 ๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„ 5 ์›์น™ - SOLID
      • CH06 ์Šคํ”„๋ง์ด ์‚ฌ๋ž‘ํ•œ ๋””์ž์ธ ํŒจํ„ด
      • CH07 ์Šคํ”„๋ง ์‚ผ๊ฐํ˜•๊ณผ ์„ค์ • ์ •๋ณด
      • (๋ถ€๋ก) ๋žŒ๋‹ค(lambda)
    • ๊ฐ์ฒด์ง€ํ–ฅ์˜ ์‚ฌ์‹ค๊ณผ ์˜คํ•ด
      • CH01 ํ˜‘๋ ฅํ•˜๋Š” ๊ฐ์ฒด๋“ค์˜ ๊ณต๋™์ฒด
      • CH02 ์ด์ƒํ•œ ๋‚˜๋ผ์˜ ๊ฐ์ฒด
      • CH03 ํƒ€์ž…๊ณผ ์ถ”์ƒํ™”
      • CH04 ์—ญํ• , ์ฑ…์ž„, ํ˜‘๋ ฅ
      • CH05 ์ฑ…์ž„๊ณผ ๋ฉ”์‹œ์ง€
      • CH06 ๊ฐ์ฒด ์ง€๋„
      • CH07 ํ•จ๊ป˜ ๋ชจ์œผ๊ธฐ
      • (+) ์ธํ„ฐํŽ˜์ด์Šค ๊ฐœ๋… ๋ฐ”๋กœ์žก๊ธฐ
    • ๋„๋ฉ”์ธ ์ฃผ๋„ ๊ฐœ๋ฐœ ์‹œ์ž‘ํ•˜๊ธฐ
      • CH01 ๋„๋ฉ”์ธ ๋ชจ๋ธ ์‹œ์ž‘ํ•˜๊ธฐ
      • CH02 ์•„ํ‚คํ…์ฒ˜ ๊ฐœ์š”
      • CH03 ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ
      • CH04 ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ์™€ ๋ชจ๋ธ ๊ตฌํ˜„
      • CH05 ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA๋ฅผ ์ด์šฉํ•œ ์กฐํšŒ ๊ธฐ๋Šฅ
      • CH06 ์‘์šฉ ์„œ๋น„์Šค์™€ ํ‘œํ˜„ ์˜์—ญ
      • CH07 ๋„๋ฉ”์ธ ์„œ๋น„์Šค
      • CH08 ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ
      • CH09 ๋„๋ฉ”์ธ ๋ชจ๋ธ๊ณผ ๋ฐ”์šด๋””๋“œ ์ปจํ…์ŠคํŠธ
      • CH10 ์ด๋ฒคํŠธ
      • CH11 CQRS
    • ์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ
      • CH01 JPA ์†Œ๊ฐœ
      • CH02 JPA ์‹œ์ž‘
      • CH03 ์˜์†์„ฑ ๊ด€๋ฆฌ
      • CH04 ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘
      • CH05 ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘ ๊ธฐ์ดˆ
      • CH06 ๋‹ค์–‘ํ•œ ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘
      • CH07 ๊ณ ๊ธ‰ ๋งคํ•‘
      • CH08 ํ”„๋ก์‹œ์™€ ์—ฐ๊ด€๊ด€๊ณ„ ๊ด€๋ฆฌ
      • CH09 ๊ฐ’ ํƒ€์ž…
      • CH10 ๊ฐ์ฒด์ง€ํ–ฅ ์ฟผ๋ฆฌ ์–ธ์–ด
      • CH11 ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ œ์ž‘
      • CH12 ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA
      • CH13 ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ์˜์†์„ฑ ๊ด€๋ฆฌ
      • CH14 ์ปฌ๋ ‰์…˜๊ณผ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ
      • CH15 ๊ณ ๊ธ‰ ์ฃผ์ œ์™€ ์„ฑ๋Šฅ ์ตœ์ ํ™”
      • CH16 ํŠธ๋žœ์žญ์…˜๊ณผ ๋ฝ, 2์ฐจ ์บ์‹œ
    • ์†Œํ”„ํŠธ์›จ์–ด ์„ธ์ƒ์„ ์—ฌ๋Š” ์ปดํ“จํ„ฐ๊ณผํ•™
      • CH01 ์ปดํ“จํ„ฐ ๊ณผํ•™ ์†Œ๊ฐœ
      • CH02 ๋ฐ์ดํ„ฐ ํ‘œํ˜„๊ณผ ๋””์ง€ํ„ธ ๋…ผ๋ฆฌ
    • ์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ”
      • 1 ์žฅ ๋“ค์–ด๊ฐ€๊ธฐ
      • 2์žฅ ๊ฐ์ฒด ์ƒ์„ฑ๊ณผ ํŒŒ๊ดด
        • [01] ์ƒ์„ฑ์ž ๋Œ€์‹  ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ๊ณ ๋ คํ•˜๋ผ
        • [02] ์ƒ์„ฑ์ž์— ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งŽ๋‹ค๋ฉด ๋นŒ๋”๋ฅผ ๊ณ ๋ คํ•˜๋ผ
        • [03] private ์ƒ์„ฑ์ž๋‚˜ ์—ด๊ฑฐ ํƒ€์ž…์œผ๋กœ ์‹ฑ๊ธ€ํ„ด์ž„์„ ๋ณด์ฆํ•˜๋ผ
        • [04] ์ธ์Šคํ„ด์Šคํ™”๋ฅผ ๋ง‰์œผ๋ ค๊ฑฐ๋“  private ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ผ
        • [05] ์ž์›์„ ์ง์ ‘ ๋ช…์‹œํ•˜์ง€ ๋ง๊ณ  ์˜์กด ๊ฐ์ฒด ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๋ผ
        • [06] ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ์„ ํ”ผํ•˜๋ผ
        • [07] ๋‹ค ์“ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•˜๋ผ
        • [08] finalizer ์™€ cleaner ์‚ฌ์šฉ์„ ํ”ผํ•˜๋ผ
        • [09] try-finally ๋ณด๋‹ค๋Š” try-with-resources ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ
      • 3์žฅ ๋ชจ๋“  ๊ฐ์ฒด์˜ ๊ณตํ†ต ๋ฉ”์„œ๋“œ
        • [10] equals๋Š” ์ผ๋ฐ˜ ๊ทœ์•ฝ์„ ์ง€์ผœ ์žฌ์ •์˜ํ•˜๋ผ
        • [11] equals ๋ฅผ ์žฌ์ •์˜ํ•˜๋ ค๊ฑฐ๋“  hashCode๋„ ์žฌ์ •์˜ํ•˜๋ผ
        • [12] toString ์„ ํ•ญ์ƒ ์žฌ์ •์˜ํ•˜๋ผ
        • [13] clone ์žฌ์ •์˜๋Š” ์ฃผ์˜ํ•ด์„œ ์ง„ํ–‰ํ•˜๋ผ
        • [14] Comparable ์„ ๊ตฌํ˜„ํ• ์ง€ ๊ณ ๋ คํ•˜๋ผ
      • 4์žฅ ํด๋ž˜์Šค์™€ ์ธํ„ฐํŽ˜์ด์Šค
        • [15] ํด๋ž˜์Šค์™€ ๋ฉค๋ฒ„์˜ ์ ‘๊ทผ ๊ถŒํ•œ์„ ์ตœ์†Œํ™”ํ•˜๋ผ
  • ํ† ํ”ฝ
    • ์„œ๋ฒ„ ๋ชจ๋‹ˆํ„ฐ๋ง
      • CPU ์‚ฌ์šฉ๋Ÿ‰
      • ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰
      • ์Šค๋ ˆ๋“œ ํ’€
    • Spring Boot Monitoring
      • Spring actuator
      • Spring eureka
      • Prometheus
      • grafana
      • Spring actuator + Prometheus + grafana
    • JAVA ๋ฐ์ผ๋ฆฌ ํ† ํ”ฝ
      • ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜(memory leak)
      • ๊ฐ์ฒด ์ฐธ์กฐ์˜ ์œ ํ˜•
      • ์ปค์Šคํ…€ ์Šค๋ ˆ๋“œ ํ’€
      • Mark And Compact
      • serialVersionUID ์ดํ•ดํ•˜๊ธฐ
      • ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค
      • ๋ฉ”์†Œ๋“œ ์ฐธ์กฐ
      • equals()์™€ hashCode()๊ฐ€ ๋ฌด์—‡์ด๊ณ  ์—ญํ• ์ด ๋ฌด์—‡์ธ์ง€
      • StringBuffer vs StringBuilder
      • String vs StringBuilder, StringBuffer
      • String interning
    • JAVA GC
    • ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฌธ์ œ ํ’€๊ธฐ
      • ํ•ด์‹œ
      • ์Šคํƒ/ํ
      • ํž™(Heap)
      • ์ •๋ ฌ
      • ์™„์ „ํƒ์ƒ‰
      • DFS/BFS
    • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ตฌ์„ฑ ๋ฐ ์ž‘๋™ ํ๋ฆ„
    • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค JOIN ์›๋ฆฌ
    • ๊ฐ์ฒด์ง€ํ–ฅ์ƒํ™œ์ฒด์กฐ ์›์น™
    • ์ƒํƒœ(state), ์ƒ์†(inheritance), ํ•ฉ์„ฑ(composition) ์˜ ์ƒ๊ด€๊ด€๊ณ„
    • java enum์€ ๋ฉ”๋ชจ๋ฆฌ์— ์–ธ์ œ, ์–ด๋–ป๊ฒŒ ํ• ๋‹น๋˜๋Š”๊ฐ€
    • Checked Exception vs UnChecked Exception
    • Reactive Streams ์›๋ฆฌํƒ๊ตฌ - ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ ์ง์ ‘ ์ž‘์„ฑํ•ด๋ณด๊ธฐ
    • Flutter Basic
    • Flutter StatefulWidget ์ƒ๋ช…์ฃผ๊ธฐ
    • Flutter ๊ฐ€ ์œ„์ ฏ์„ ๊ทธ๋ฆฌ๋Š” ์›๋ฆฌ
    • Flutter ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜
      • application layer
        • ํŒจํ‚ค์ง€ ๊ตฌ์กฐ ๋ฐ ๋ ˆ์ด์–ด ์„ค๋ช…
        • environment
        • dependency injection
        • go_router
        • foreground & background
        • ๋‹ค๊ตญ์–ด์ฒ˜๋ฆฌ (l10n, i18n)
        • Global ์ฒ˜๋ฆฌ(์‹œ์Šคํ…œ ์ ๊ฒ€, fore->back ๋“ฑ)
        • connection_manager
        • permission_manager
        • push_notification_manager
        • firebase ์—ฐ๋™
      • data layer
        • ํŒจํ‚ค์ง€ ๊ตฌ์กฐ ๋ฐ ๋ ˆ์ด์–ด ์„ค๋ช…
        • network
        • repository
      • domain layer
        • ํŒจํ‚ค์ง€ ๊ตฌ์กฐ ๋ฐ ๋ ˆ์ด์–ด ์„ค๋ช…
      • presentation layer
        • ํŒจํ‚ค์ง€ ๊ตฌ์กฐ ๋ฐ ๋ ˆ์ด์–ด ์„ค๋ช…
        • resources
    • ๊ธฐ์ˆ  ๊ด€๋ จ ํฌ์ŠคํŒ… ์ฝ๊ธฐ
  • ๊ธฐํƒ€
    • ์ž‘์—…์ผ์ง€
      • 2023. 10
      • 2023. 09
      • 2023. 08
      • 2023. 07
      • 2023. 06
      • 2023. 05
      • 2023. 04
      • 2023. 03
      • 2023. 02
      • 2023. 01
      • 2022. 12
    • Business Model
      • ์•„์ด๋””์–ด ๋ถˆํŒจ์˜ ๋ฒ•์น™
      • ๋ฆฐ ๋ชจ๋ฐ”์ผ ์•ฑ ๊ฐœ๋ฐœ
      • ๋ฆฐ ์Šคํƒ€ํŠธ์—…
      • ์ œ๋กœํˆฌ์›
      • MIT ์Šคํƒ€ํŠธ์—… ๋ฐ”์ด๋ธ”
      • ๋ฆฐ์น˜ํ•€
    • ๋ฐฑ๋กœ๊ทธ ์ข…ํ•ฉ
Powered by GitBook
On this page
  • ๊ตฌ๋™์›๋ฆฌ
  • ๊ธฐ๋ณธ์ ์ธ annotation ์ •๋ฆฌ (JUnit 5 ๊ธฐ์ค€)
  • @BeforeAll / @AfterAll
  • @BeforeEach / @AfterEach
  • @Disabled
  • ํ…Œ์ŠคํŠธ ์ด๋ฆ„ ํ‘œ๊ธฐํ•˜๊ธฐ
  • @DisplayNameGeneration
  • @DisplayName
  • JUnit 5 Assertion
  • JUnit 5 ํƒœ๊น…๊ณผ ํ•„ํ„ฐ๋ง
  • @Tag
  • ํ•„ํ„ฐ๋ง
  • ์ปค์Šคํ…€ ํƒœ๊ทธ
  • JUnit 5: ํ…Œ์ŠคํŠธ ๋ฐ˜๋ณตํ•˜๊ธฐ
  • @RepeatedTest
  • @ParameterizedTest
  • @ConvertWith + @ParameterizedTest
  • @CsvSource + @AggregateWith + @ParameterizedTest
  • ๊ทธ ์™ธ ๊ฐ•์˜ ์ž๋ฃŒ์— ์†Œ๊ฐœ๋œ ๊ฒƒ๋“ค(๋‹ค์–‘ํ•˜๊ฒŒ ์ ์žฌ์ ์†Œ์— ์ž˜ ์จ๋จน์ž)
  • JUnit 5 ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค
  • JUnit ํ…Œ์ŠคํŠธ ์ˆœ์„œ
  • junit-platform.properties
  • JUnit 5 ํ™•์žฅ ๋ชจ๋ธ
  1. ๊ฐ•์˜
  2. ๋” ์ž๋ฐ”, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•

CH01 JUnit 5

Previous๋” ์ž๋ฐ”, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•NextCH02 Mockito

Last updated 1 year ago

๊ตฌ๋™์›๋ฆฌ

๋งค๋ฒˆ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์งœ๋Š”๋ฐ์— ๊ณต์„ ๋งŽ์ด ๋“ค์ด๊ธด ํ–ˆ๋Š”๋ฐ, ์ •์ž‘ ํ…Œ์ŠคํŠธ๊ฐ€ ๋™์ž‘ ํ•˜๋Š” ์›๋ฆฌ์— ๋Œ€ํ•ด์„œ๋Š” ๊ด€์‹ฌ์„ ๋‘์ง€ ์•Š์•˜๋˜ ๊ฒƒ ๊ฐ™๋‹ค.

IDE๊ฐ€ JUnit Platform Launcher๋ฅผ ๋กœ๋“œํ•˜๊ณ  JUnit Platform Launcher๊ฐ€ JUnit Platform์˜ ํ…Œ์ŠคํŠธ ์—”์ง„์„ ๋กœ๋“œํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ…Œ์ŠคํŠธ ์—”์ง„์ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š”๋ฐ ์ด ์ง์ „์— ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์ด ์ˆ˜ํ–‰๋œ๋‹ค.

์ˆœ์„œ์ƒ ์ •๋ฆฌ๋ฅผ ํ•˜์ž๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  1. IDE๊ฐ€ JUnit Platform Launcher๋ฅผ ๋กœ๋“œ

  2. JUnit Platform Launcher๊ฐ€ JUnit Platform์˜ ํ…Œ์ŠคํŠธ ์—”์ง„์„ ๋กœ๋“œ

  3. ํด๋ž˜์Šค ๋กœ๋”ฉ ๋ฐ ์ปดํฌ๋„ŒํŠธ ์Šค์บ”

  4. ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์‹คํ–‰

์œ„ ๊ทธ๋ฆผ์€ JUnit ์ „์ฒด๋ฅผ ๊ฐ„๋žตํ•˜๊ฒŒ ๋„์‹ํ™” ํ•œ ๊ฒƒ์ด๊ณ  Jupiter๋Š” JUnit 5 ์˜ ๊ตฌํ˜„์ฒด API ๋ผ๊ณ  ์ดํ•ดํ•˜๋ฉด ๋œ๋‹ค.

๊ธฐ๋ณธ์ ์ธ annotation ์ •๋ฆฌ (JUnit 5 ๊ธฐ์ค€)

NEXTSTEP ์—์„œ ์•„์ฃผ ๊ฐ•ํ•˜๊ฒŒ ๊ฐ•์กฐํ•˜๋Š” ๊ฒƒ์ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ์ด๊ณ  ๋“ค์—ˆ๋˜ ๋Œ€๋ถ€๋ถ„์˜ ๊ฐ•์˜์—์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ๋‹ค์–‘ํ•œ ํ™œ์šฉ์— ๋Œ€ํ•ด์„œ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›์•˜๋‹ค. ์ง€๊ธˆ ์ด ๊ฐ•์˜๋Š” ์‚ฌ์‹ค ์™„๊ฐ•์„ ๊ฝค ์˜ค๋ž˜์ „์— ํ•˜๊ณ  ๋‹ค์‹œ ์ •๋ฆฌ๋ฅผ ํ•˜๋Š” ์ฐจ์›์—์„œ ๋ณด๊ณ  ์žˆ๋Š”๋ฐ, ๋‹น์‹œ์—๋Š” ๋ชฐ๋ž์œผ๋‚˜ ์ง€๊ธˆ ๋ณด๋‹ˆ NEXTSTEP ์—์„œ ํ”ผ๋“œ๋ฐฑ ํ•ด์ฃผ๋Š” ์ˆ˜์ค€์˜ ๋†’์€ ๋””ํ…Œ์ผ์„ ๊ฐ•์˜์—์„œ ๋‹ค๋ฃจ๊ณ  ์žˆ๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ๊ฐ•์˜์˜ ํ€„๋ฆฌํ‹ฐ๊ฐ€ ์ข‹์€ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

์•„๋ž˜๋Š” ๊ณผ๊ฑฐ์— ๊ฐ•์˜๋ฅผ ๋“ค์„ ๋•Œ ์ •๋ฆฌํ•œ ๋…ธํŠธ์ด๋‹ค.

@BeforeAll / @AfterAll

ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๊ฐ€ ์„ ์–ธ๋œ ํด๋ž˜์Šค์˜ ๋ชจ๋“  @Test ๋“ค์ด ์‹œ์ž‘๋˜๊ธฐ ์ „๊ณผ ํ›„์— ํ•œ ๋ฒˆ์”ฉ ์‹คํ–‰๋˜๋ฉฐ static ์œผ๋กœ ๋งŒ๋“ค์–ด ์ค˜์•ผํ•จ. ์™œ๋ƒํ•˜๋ฉด ๋‚˜์ค‘์— ๋‹ค๋ฃจ๊ฒ ์ง€๋งŒ @TestInstance์˜ ๋ผ์ดํ”„์‚ฌ์ดํด์ด ๊ฐ๊ฐ์˜ @Test ๋งˆ๋‹ค ์ƒˆ๋กœ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ๊ฐ์˜ ์ธ์Šคํ„ด์Šค์—์„œ @BeforeAll / @AfterAll๋กœ ๋งŒ๋“ค์–ด์ค€ ๋ฉ”์†Œ๋“œ์— ์ ‘๊ทผํ•˜๋ ค๋ฉด static์ด ํ•„์š”ํ•˜๋‹ค.

๋ฐ˜๋Œ€๋กœ @TestInstance์˜ ๋ผ์ดํ”„์‚ฌ์ดํด์„ ํด๋ž˜์Šค๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ํ•˜๋‚˜์˜ ํด๋ž˜์Šค์—์„œ ์—ฌ๋Ÿฌ ํ…Œ์ŠคํŠธ๋“ค์ด ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— static ์œผ๋กœ ํ•ด์ค„ ํ•„์š”๊ฐ€ ์—†์–ด์ง„๋‹ค.

@TestInstance(TestInstance.Lifecycle.PER_METHOD) // default
//@TestInstance(TestInstance.Lifecycle.PER_CLASS)

@BeforeEach / @AfterEach

ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๊ฐ€ ์„ ์–ธ๋œ ํด๋ž˜์Šค์˜ ๋ชจ๋“  @Test ๊ฐ๊ฐ์˜ ์ „๊ณผ ํ›„์— ์‹คํ–‰(@Test ๋ฉ”์†Œ๋“œ ์ˆ˜๋งŒํผ ์ „๊ณผ ํ›„์— ์‹คํ–‰๋จ)

@Disabled

์ด ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ณ„๊ฑฐ ์•„๋‹Œ๋ฐ ํš๊ธฐ์ ์ด๋‹ค. ์™œ๋ƒ๋ฉด ๋‚˜๋Š” ํ…Œ์ŠคํŠธ์šฉ์œผ๋กœ ์“ด๊ฑธ ์ฃผ์„์ฒ˜๋ฆฌํ•ด์„œ ๋Œ๋ฆฌ๊ณ , ์ฃผ์„ ํ’€๊ณ  ๋‹ค์‹œ ๋Œ๋ฆฌ๊ณ  ํ–ˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํ”„๋กœ๋•์„  ์ฝ”๋“œ์— ์จ๋จน๋Š” ๊ฒฝ์šฐ๋Š” ๋งŒ์ผ์„ ์œ„ํ•ด์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋‚จ๊ฒจ๋‘๊ณ  ์‹ถ์ง€๋งŒ ์ฃผ์„์ฒ˜๋ฆฌ๋กœ ํ•ด๋‘๊ธฐ ์‹ซ์œผ๋ฉด ์จ๋จน์œผ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

ํ…Œ์ŠคํŠธ ์ด๋ฆ„ ํ‘œ๊ธฐํ•˜๊ธฐ

@DisplayNameGeneration

ํ•ด๋‹น ํด๋ž˜์Šค ์ „์ฒด์˜ @Test์— ๋Œ€ํ•œ ์ด๋ฆ„์„ ํ‘œ๊ธฐํ•˜๋Š” ์ „๋žต์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Œ

@DisplayName

๊ฐœ๋ณ„ @Test์˜ ์ด๋ฆ„์„ ์„ค์ •(@DisplayNameGeneration๋ณด๋‹ค ์šฐ์„ ์ˆœ์œ„ ๋†’์Œ)

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class StudyTest {
}

JUnit 5 Assertion

๊ฐœ์ธ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์— ๋Œ€ํ•œ ์Šต๊ด€ ์ž์ฒด๊ฐ€ NEXTSTEP ๊ฐ•์˜๋ฅผ ๋“ค์œผ๋ฉด์„œ ๋งŽ์ด ํ˜•์„ฑ์ด ๋˜์—ˆ๋Š”๋ฐ, NEXTSTEP์—์„œ org.assertj.core.api.Assertions ์„ ๋งŽ์ด ํ™œ์šฉํ•˜๋„๋ก ๊ฐ€์ด๋“œ ํ•ด์ค˜์„œ jupiter ๊ฒƒ์€ ๊ฐœ์ธ์ ์œผ๋กœ ์ž˜ ์•ˆ์“ด๋‹ค. ์ด๊ฑด ํŒ€ ์ปจ๋ฒค์…˜์„ ๋”ฐ๋ผ๊ฐ€๋ฉด ์ข‹์„ ๋“ฏ ํ•˜๊ณ , ์•„๋ž˜๋Š” ์˜ˆ์ „์— ์ •๋ฆฌํ•ด๋‘” ๋…ธํŠธ๋ฅผ ๊ทธ๋Œ€๋กœ ๋‚จ๊ธด๋‹ค.

  • assertEquals(expected, actual) : ์‹ค์ œ ๊ฐ’์ด ๊ธฐ๋Œ€ํ•œ ๊ฐ’๊ณผ ๊ฐ™์€์ง€ ํ™•์ธ(ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆœ์„œ๊ฐ€ ๋ฌด๊ด€ํ•˜๊ธด ํ•˜์ง€๋งŒ ์ขŒ์ธก์ด ๊ธฐ๋Œ€๊ฐ’, ์šฐ์ธก์ด ์ถœ๋ ฅ๊ฐ’์ž„์„ ์•Œ๊ณ  ์“ฐ์ž)

  • assertNotNull(actual) : ์ถœ๋ ฅ๊ฐ’์ด null์ด ์•„๋‹Œ์ง€ ํ™•์ธ

  • assertTrue(boolean) : ๋‹ค์Œ ์กฐ๊ฑด์ด ์ฐธ์ธ์ง€ ํ™•์ธ

  • assertAll(executablesโ€ฆ) : ํ•˜๋‚˜์˜ @Test์—์„œ ๋‘ ๊ฐœ ์ด์ƒ์˜ assert๋ฌธ์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ์ฒซ๋ฒˆ์งธ assert์—์„œ fail์ด ๋  ๊ฒฝ์šฐ ๋‘๋ฒˆ์งธ assert๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š์Œ. ์ด ๋•Œ ๋‘ assert๋ฅผ assertAll๋กœ ๊ฐ์‹ธ์ฃผ๋ฉด ๋‘˜๋‹ค ๋…๋ฆฝ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • assertThrows(expectedType, executable) : ์˜ˆ์™ธ ๋ฐœ์ƒ ํ™•์ธ

  • assertTimeout(duration, executable) : ํŠน์ • ์‹œ๊ฐ„ ์•ˆ์— ์‹คํ–‰์ด ์™„๋ฃŒ๋˜๋Š”์ง€ ํ™•์ธ

    @Test
    @DisplayName("์Šคํ„ฐ๋”” ๋งŒ๋“ค๊ธฐ")
    void createNewStudy() {
        Study study = Study.builder()
                .studyStatus(StudyStatus.DRAFT)
                .limit(20)
                .build();
        assumeTrue(study != null);
        assertAll(
                () -> assertEquals(StudyStatus.DRAFT, study.getStudyStatus(), "์Šคํ„ฐ๋””๋ฅผ ์ฒ˜์Œ ๋งŒ๋“ค๋ฉด ์ƒํƒœ๊ฐ’์ด DRAFT ์—ฌ์•ผ ํ•œ๋‹ค."),
                () -> assertTrue(study.getLimit() > 10, "์Šคํ„ฐ๋””์˜ ์ตœ์†Œ ์ธ์›์€ 10๋ช…์„ ์ดˆ๊ณผํ•ด์•ผ ํ•œ๋‹ค.")
        );
    }

ํ…Œ์ŠคํŠธ ์ž์ฒด๊ฐ€ ํ•˜๋‚˜๋ผ๋„ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— assertAll์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๊ฒฐ๊ตญ ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ•˜๋ฉด ํ•ด๋‹น @Test ์ž์ฒด๊ฐ€ ์‹คํŒจํ•œ ๊ฒƒ์œผ๋กœ ์ธ์‹ํ•  ์ˆ˜ ์žˆ์–ด์„œ ๋ฌธ์ œ๋  ๊ฒƒ์€ ์—†๋‹ค.

ํ•˜์ง€๋งŒ ํ•˜๋‚˜์˜ @Test ๋‚ด์— ๋‘ ๊ฐœ ์ด์ƒ์˜ assert ๋ฌธ์ด ์žˆ๊ณ , ํ…Œ์ŠคํŠธ๋ฅผ ํ–ˆ์„ ๋•Œ ์–ด๋–ค ๊ฒƒ์€ ์‹คํŒจํ–ˆ๊ณ  ์–ด๋–ค ๊ฒƒ์€ ํ†ต๊ณผํ–ˆ๋Š”์ง€๋ฅผ ๊ตฌ๋ถ„ํ•˜์—ฌ ์•Œ ์ˆ˜ ์žˆ๋‹ค๋ฉด ๊ฐœ๋ฐœ ์ž์ฒด๊ฐ€(=ํ…Œ์ŠคํŠธ ์ž์ฒด๊ฐ€) ๋” ์šฉ์ดํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— assertAll์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

    @Test
    void statusTest() {
        Study study = new Study();
        assertEquals(StudyStatus.STARTED, study.getStudyStatus(), "์ฒ˜์Œ ์Šคํ„ฐ๋””๋ฅผ ๋งŒ๋“ค๋ฉด ์ƒํƒœ๋Š” DRAFT ์—ฌ์•ผ ํ•œ๋‹ค");
        assertEquals(StudyStatus.STARTED, study.getStudyStatus(), () -> "์ฒ˜์Œ ์Šคํ„ฐ๋””๋ฅผ ๋งŒ๋“ค๋ฉด ์ƒํƒœ๋Š” DRAFT ์—ฌ์•ผ ํ•œ๋‹ค");
    }

๋ฉ”์„ธ์ง€๋ฅผ ๊ทธ๋ƒฅ ๊ทธ๋Œ€๋กœ ๋„ฃ์–ด์ฃผ๋Š” ๊ฒƒ๊ณผ ๋žŒ๋‹ค์‹์œผ๋กœ ๋„ฃ์–ด์ฃผ๋Š” ๋ฐฉ๋ฒ• ๋‘˜๋‹ค ๋ฉ”์„ธ์ง€ ์ฒ˜๋ฆฌ์—๋Š” ๋ฌธ์ œ๊ฐ€ ์—†๋Š”๋ฐ, ๋žŒ๋‹ค์‹์œผ๋กœ ํ•  ๊ฒฝ์šฐ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ–ˆ์„ ๋•Œ์—๋งŒ ๋ฉ”์„ธ์ง€ ์—ฐ์‚ฐ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ๋งŒ์•ฝ ์ฒ˜๋ฆฌํ•  ๋ฉ”์„ธ์ง€ ์—ฐ์‚ฐ์˜ ์ฒ˜๋ฆฌ๋น„์šฉ์ด ๋ถ€๋‹ด์ด ๋  ์ˆ˜์ค€์ด๋ผ๋ฉด ๋žŒ๋‹ค์‹์œผ๋กœ ๋„ฃ์–ด์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๊ทธ๋ž˜์„œ ๊ฒฐ๋ก ์ ์œผ๋กœ๋Š” ๋ชจ๋“  ๋ฉ”์„ธ์ง€๋ฅผ ์ €๋ ‡๊ฒŒ ๋žŒ๋‹ค์‹์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ๋Š” ์Šต๊ด€์„ ๋“ค์ด๋Š” ๊ฒƒ์ด ์ข‹๊ฒ ๋‹ค.

    public Study(int limit) {
        if (limit < 0) {
            throw new IllegalArgumentException(Constant.studyLimitErrorMessage);
        }

        this.limit = limit;
    }
    @Test
    void limitTest() {
        IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
            Study study = new Study(-10);
        });
        assertEquals(exception.getMessage(), Constant.studyLimitErrorMessage);
    }

assertThrows๋ฅผ ๋‹จ์ˆœํžˆ ์›ํ•˜๋Š” ์—๋Ÿฌ ํƒ€์ž…์˜ ๊ฐ์ง€์—๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ์ด์ƒ์œผ๋กœ ์—๋Ÿฌ ๋ฉ”์„ธ์ง€์˜ ์ผ์น˜์„ฑ ์—ฌ๋ถ€๊นŒ์ง€ ๋ฝ‘์•„์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋™์ผํ•œ ์—๋Ÿฌ ์œ ํ˜• ๋‚ด์—์„œ ์กฐ๊ฑด์— ๋”ฐ๋ผ ์—๋Ÿฌ ๋ฉ”์„ธ์ง€๋ฅผ ๋‹ค์–‘ํ•˜๊ธฐ ๋ถ„๊ธฐํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค.

JUnit 5 ํƒœ๊น…๊ณผ ํ•„ํ„ฐ๋ง

@Tag

ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน์„ ๋งŒ๋“ค๊ณ  ์›ํ•˜๋Š” ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน๋งŒ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ. intellij์˜ test configuration ์กฐ์ž‘(test kind = Tags, Tag expression = custom tag)์„ ํ†ตํ•ด์„œ ํŠน์ • ํƒœ๊ทธ๋งŒ ํ…Œ์ŠคํŠธ ๋˜๋„๋ก ํ•œ๋‹ค.

ํ•„ํ„ฐ๋ง

์ปค์Šคํ…€ ํƒœ๊ทธ

์ปค์Šคํ…€ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด @Test์— ๋ถ€์—ฌํ•ด์ค„ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์„ค์ •๋“ค์„ ๋‹จ์ˆœํ™”ํ•˜๊ณ  ์ค‘๋ณต์„ ์ œ๊ฑฐํ•˜์—ฌ ์ ์šฉ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. ํŠนํžˆ @Tag๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์ปค์Šคํ…€ ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•˜์—ฌ type safeํ•˜๊ฒŒ @Tag๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ด์ ์ด ์žˆ๋‹ค. ๋‹ค์ˆ˜์˜ @Tag์— ๋งค๋ฒˆ ์›ํ•˜๋Š” tag๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ ๋ณด๋‹ค ์„ค์ •ํ•ด๋‘” tag๊ฐ€ ์ ์šฉ๋œ ์ปค์Šคํ…€ ํƒœ๊ทธ๋ฅผ ์ผ๊ด„๋กœ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ณง type safeํ•œ ๋ฐฉ๋ฒ•์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Test
@Tag("development")
public @interface DevelopmentTest {
}

JUnit 5: ํ…Œ์ŠคํŠธ ๋ฐ˜๋ณตํ•˜๊ธฐ

@RepeatedTest

ํŠน์ • ํšŸ์ˆ˜๋งŒํผ ํ…Œ์ŠคํŠธ๋ฅผ ๋ฐ˜๋ณตํ•˜์—ฌ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ํ…Œ์ŠคํŠธ ์ฝ˜์†”์ฐฝ์— ๋‚˜์˜ค๋Š” ํ…Œ์ŠคํŠธ๋ช…๊ณผ ๋ฐ˜๋ณต ํšŸ์ˆ˜ ๋“ฑ์„ ์ปค์Šคํ…€ํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

    @RepeatedTest(value = 10, name = "{displayName}, {currentRepetition} / {totalRepetitions}")
    @DisplayName("์Šคํ„ฐ๋”” ๋ฐ˜๋ณต ํ…Œ์ŠคํŠธ")
    void repeatedTest(RepetitionInfo repetitionInfo) {
        System.out.println(repetitionInfo.getCurrentRepetition() + " / " + repetitionInfo.getTotalRepetitions());
    }

๋งŒ์•ฝ placeholder ๋“ค์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด Build, Execution, Deployment -> Build Tools -> Gradle๋กœ ์ด๋™ํ•œ ๋‹ค์Œ Run tests using ์„ Gradle -> Intellij IDE ๋กœ ์ˆ˜์ •ํ•˜๋ฉด ๋œ๋‹ค.

@ParameterizedTest

@ValueSource๋ฅผ ์ด์šฉํ•ด์„œ ํ•˜๋‚˜์˜ @Test์— ์—ฌ๋Ÿฌ ๋‹ค๋ฅธ ๋งค๊ฐœ๋ณ€์ˆ˜(์›ํ•˜๋Š” ๋Œ€๋กœ ์„ ์–ธ๋œ)๋ฅผ ๋Œ€์ž…ํ•ด๊ฐ€๋ฉฐ ๋ฐ˜๋ณต ์‹คํ–‰ํ•œ๋‹ค.

์ถ”๊ฐ€์ ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์˜ต์…˜

  • @NullSource

  • @EmptySource

  • @NullAndEmptySource

    @DisplayName("parameterized Test")
    @ParameterizedTest(name = "{displayName} : {index} // {0}")
    @ValueSource(strings = {"first", "second", "third", "fourth", "fifth"})
    @NullSource
    @EmptySource
    //@NullAndEmptySource
    void parametersTest(String param) {
        System.out.println(param);
    }

@ConvertWith + @ParameterizedTest

์ปค์Šคํ…€ํ•œ ์ปจ๋ฒ„ํ„ฐ๋ฅผ ์ด์šฉํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉ. ๋ฐ›์€ ์ธ์ž๊ฐ’์œผ๋กœ ๋ฐ”๋กœ ์›ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.(๋ฐ›์•„์„œ ๋‚ด๋ถ€์—์„œ ๋งŒ๋“ค์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ๋งŒ๋“ค์–ด์ง„ ๊ฐ์ฒด๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์Œ) ํ•ด๋‹น ์˜ˆ์ œ๋Š” SimpleArgumentConverter๋ฅผ ์‚ฌ์šฉํ•œ ์˜ˆ์ œ๋กœ 2๊ฐœ ์ด์ƒ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋Š” ์—†๋‹ค.

    @ParameterizedTest
    @ValueSource(ints = {20, 30, 40, 50})
    void converterTest(@ConvertWith(StudyConverter.class) Study study) {
        System.out.println(study.getLimit());
    }

    static class StudyConverter extends SimpleArgumentConverter {

        @Override
        protected Object convert(Object source, Class<?> targetType) throws ArgumentConversionException {
            assertEquals(Study.class, targetType, "Can only convert Study");
            return Study.builder().limit(Integer.parseInt(source.toString())).build();
        }
    }

@CsvSource + @AggregateWith + @ParameterizedTest

๋ณต์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ์ด๋ฅผ ๋ฐ”๋กœ ๊ฐ์ฒด๋กœ ๋ฐ›์•„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„๋•Œ ์‚ฌ์šฉ

    @ParameterizedTest
    @CsvSource({"10, ์ž๋ฐ”", "20, ์Šคํ”„๋ง"})
    void aggregateTest(@AggregateWith(StudyAggregator.class) Study study) {
        System.out.println("limit : " + study.getLimit());
        System.out.println("name : " + study.getName());
    }

    static class StudyAggregator implements ArgumentsAggregator {

        @Override
        public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) throws ArgumentsAggregationException {
            return Study.builder().limit(accessor.getInteger(0)).name(accessor.getString(1)).build();
        }
    }

๊ทธ ์™ธ ๊ฐ•์˜ ์ž๋ฃŒ์— ์†Œ๊ฐœ๋œ ๊ฒƒ๋“ค(๋‹ค์–‘ํ•˜๊ฒŒ ์ ์žฌ์ ์†Œ์— ์ž˜ ์จ๋จน์ž)

  • @ValueSource

  • @NullSource, @EmptySource, @NullAndEmptySource

  • @EnumSource

  • @MethodSource

  • @CsvSource

  • @CvsFileSource

  • @ArgumentSource

JUnit 5 ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค

JUnit์€ ๊ธฐ๋ณธ์ ์œผ๋กœ @Test ๋งˆ๋‹ค ํ•ด๋‹น @Test๊ฐ€ ์†ํ•œ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ ๋‹ค. ํ•˜๋‚˜์˜ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— ๋‘ ๊ฐœ์˜ @Test ๊ฐ€ ์žˆ์œผ๋ฉด ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค ์ „์ฒด๋ฅผ ํ…Œ์ŠคํŠธ์‹œ์— ๊ธฐ๋ณธ์ ์œผ๋กœ ํด๋ž˜์Šค๊ฐ€ ๋‘ ๊ฐœ ์ƒ๊ธด๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

@TestInstance(TestInstance.Lifecycle.PER_METHOD)

์ด๊ฒƒ์ด ๊ธฐ๋ณธ ๊ฐ’์ด๋‹ค. ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค์˜ ๋ผ์ดํ”„ ์‚ฌ์ดํด์ด '๋ฉ”์†Œ๋“œ ๋งˆ๋‹ค' ๋กœ ์ •ํ•ด์ง„๋‹ค. (๋‹น์—ฐํžˆ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค) ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋ณด์ž.

package com.example.securitysample.sample;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_METHOD) // default
//@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class SampleTest {

    int value = 0;
    User user = new User();

    @Test
    void test1() {
        value++;
        System.out.println(value);
        System.out.println(user);
        Assertions.assertThat(value).isEqualTo(1);
    }

    @Test
    void test2() {
        value++;
        System.out.println(value);
        System.out.println(user);
        Assertions.assertThat(value).isEqualTo(1);
    }

}
1
com.example.securitysample.sample.User@14be750c
1
com.example.securitysample.sample.User@4fe2dd02

value ๊ฐ€ ๋‘ ํ…Œ์ŠคํŠธ ์ค‘ ํ•˜๋‚˜์—์„œ๋Š” 2๊ฐ€ ์ฐํ˜€์•ผ ํ• ํ…๋ฐ ๋‘˜ ๋‹ค 1์ด ์ฐํ˜”๋‹ค. ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ user ๋ผ๋Š” ๊ฐ์ฒด์˜ ์ฃผ์†Œ๊ฐ’๋„ ๋‘ ํ…Œ์ŠคํŠธ์—์„œ ๋‹ค๋ฅธ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋‘ ํ…Œ์ŠคํŠธ์—์„œ SampleTest ๋ผ๋Š” ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋”ฐ๋กœ ๋”ฐ๋กœ ์ƒ์„ฑ๋˜์–ด ์‚ฌ์šฉ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์ด๋Š” @Test๊ฐ€ ์„œ๋กœ์—๊ฒŒ ์ฃผ๋Š” ์˜ํ–ฅ์„ ์—†์• ๊ธฐ ์œ„ํ•ด์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฉ”์†Œ๋“œ ๋ณ„๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌํ•œ ๊ธฐ๋ณธ ์ฒ ํ•™์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ…Œ์ŠคํŠธ์ธ์Šคํ„ด์Šค์˜ ๋ผ์ดํ”„์‚ฌ์ดํด ๊ธฐ๋ณธ ์ „๋žต์ด PER_METHOD ์ด๋‹ค.

PER_CLASS ๋กœ ๋ฐ”๊พธ๊ฒŒ ๋˜๋ฉด @BeforeAll๊ณผ @AfterAll ์„ static ์ฒ˜๋ฆฌ ํ•ด์ค„ ํ•„์š”๊ฐ€ ์—†์–ด์ง„๋‹ค. ์• ์ดˆ์— static ์ด์–ด์•ผ ํ–ˆ๋˜ ์ด์œ ๊ฐ€ ์ธ์Šคํ„ด์Šค๋ฅผ ํ…Œ์ŠคํŠธ ๋งˆ๋‹ค ์ƒˆ๋กœ ๋งŒ๋“œ๋‹ˆ๊นŒ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ์ „ ๋˜๋Š” ํ›„์— ํ˜ธ์ถœ์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ static ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ค€ ๊ฒƒ์ธ๋ฐ ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค์—์„œ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘๋™ ์‹œํ‚ฌ ๊ฑฐ๋ฉด static ์ผ ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

JUnit ํ…Œ์ŠคํŠธ ์ˆœ์„œ

ํ•œ ํด๋ž˜์Šค ๋‚ด์˜ @Test ๋“ค์€ ํŠน์ •ํ•œ ์ˆœ์„œ์— ์˜ํ•ด ์‹คํ–‰๋˜์ง€๋งŒ ์–ด๋–ป๊ฒŒ ๊ทธ ์ˆœ์„œ๋ฅผ ์ •ํ•˜๋Š”์ง€๋Š” ์˜๋„์ ์œผ๋กœ ๋ถ„๋ช…ํžˆ ํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ด์œ ๋Š” ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค๋ฅผ @Test ๋งˆ๋‹ค ๋…๋ฆฝ์ ์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

์ฆ‰, ์ œ๋Œ€๋กœ๋œ Unit ํ…Œ์ŠคํŠธ๋ผ๋ฉด ๊ฐ Unit test๊ฐ„์— ๋ˆ„๊ฐ€ ๋จผ์ € ์‹คํ–‰๋˜๋“  ์„œ๋กœ์—๊ฒŒ ์˜ํ–ฅ์ด ์—†์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.(๋ฉฑ๋“ฑ์„ฑ์˜ ๊ฐœ๋…๊ณผ ์–ด๋А์ •๋„ ๊ต์ง‘ํ•ฉ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐ๋œ๋‹ค)

ํ•˜์ง€๋งŒ, ๊ฒฝ์šฐ์— ๋”ฐ๋ผ์„œ ํŠน์ •ํ•œ ์ˆœ์„œ๋Œ€๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์„ ๋•Œ๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด ๋•Œ์—๋Š” @TestInstance(TestInstance.Lifecycle.PER_CLASS)๊ณผ ํ•จ๊ป˜ @TestMethodOrder๋ฅผ ํ†ตํ•ด์„œ ๋ฉ”์†Œ๋“œ๋งˆ๋‹ค ์ˆœ์„œ๋ฅผ ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.(๊ตณ์ด ๊ฐ™์ด ์“ธ ํ•„์š”๋Š” ์—†๋‹ค. ๋‹ค๋งŒ, ์ˆœ์„œ๋ฅผ ์ •ํ•œ๋‹ค๋Š” ๊ฒƒ์ด ํด๋ž˜์Šค ๋‚ด ๊ณต์œ ํ•  ์ž์›์ด ์žˆ์„ ํ™•๋ฅ ์ด ๋†’๊ธฐ์— ์˜ˆ์ œ๋ฅผ ์ด๋ ‡๊ฒŒ ๋‹ค๋ฃฌ ๊ฒƒ)

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) // @Order ๋ผ๋Š” annotation์œผ๋กœ order๋ฅผ ์ •ํ•ด์ฃผ๊ฒ ๋‹ค๊ณ  ์„ ์–ธํ•˜๋Š” ์˜๋ฏธ
class StudyTest {

// ๊ฐ ๋ฉ”์†Œ๋“œ์— @Order(int) ๋กœ ์ˆœ์„œ๋ฅผ ์ง€์ •ํ•ด์ค€๋‹ค. int๊ฐ€ ์ž‘์„์ˆ˜๋ก ๋จผ์ € ์‹คํ–‰.
}

junit-platform.properties

junit-platform.properties๋Š” JUnit ์„ค์ • ํŒŒ์ผ๋กœ, ํด๋ž˜์ŠคํŒจ์Šค ๋ฃจํŠธ (src/test/resources/)์— ๋„ฃ์–ด๋‘๋ฉด ์ ์šฉ๋œ๋‹ค.

  • ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค ๋ผ์ดํ”„์‚ฌ์ดํด ์„ค์ •

    • junit.jupiter.testinstance.lifecycle.default = per_class

  • ํ™•์žฅํŒฉ ์ž๋™ ๊ฐ์ง€ ๊ธฐ๋Šฅ

    • junit.jupiter.extensions.autodetection.enabled = true

  • @Disabled ๋ฌด์‹œํ•˜๊ณ  ์‹คํ–‰ํ•˜๊ธฐ

    • junit.jupiter.conditions.deactivate = org.junit.*DisabledCondition

  • ํ…Œ์ŠคํŠธ ์ด๋ฆ„ ํ‘œ๊ธฐ ์ „๋žต ์„ค์ •

    • junit.jupiter.displayname.generator.default = org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores

JUnit 5 ํ™•์žฅ ๋ชจ๋ธ

  • ํ™•์žฅํŒฉ ๋“ฑ๋ก ๋ฐฉ๋ฒ•

    • ์„ ์–ธ์ ์ธ ๋“ฑ๋ก @ExtendWith

    • ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋“ฑ๋ก @RegisterExtension

  • ํ™•์žฅํŒฉ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•

    • ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์กฐ๊ฑด

    • ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค ํŒฉํ† ๋ฆฌ

    • ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค ํ›„-์ฒ˜๋ฆฌ๊ธฐ

    • ํ…Œ์ŠคํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฆฌ์กธ๋ฒ„

    • ํ…Œ์ŠคํŠธ ๋ผ์ดํ”„์‚ฌ์ดํด ์ฝœ๋ฐฑ

    • ์˜ˆ์™ธ์ฒ˜๋ฆฌ

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@ExtendWith(ExecutionTimeExtension.class)
class StudyTest {
}

๋งŒ์•ฝ ์œ„์™€ ๊ฐ™์ด THRESHOLD ์™€ ๊ฐ™์€ ํŠน์ • ๊ฐ’์„ ์ƒ์ˆ˜ํ™” ํ•˜์ง€ ์•Š๊ณ  ํ…Œ์ŠคํŠธ ๋งˆ๋‹ค ๋‹ค๋ฅด๊ฒŒ ์„ค์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด @RegisterExtension์„ ์ด์šฉํ•œ๋‹ค.

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class StudyTest {

    @RegisterExtension
    ExecutionTimeExtension executionTimeExtension = new ExecutionTimeExtension(1000L);
}

public class ExecutionTimeExtension implements BeforeTestExecutionCallback, AfterTestExecutionCallback {

    private final long threshold;

    public ExecutionTimeExtension(long threshold) {
        this.threshold = threshold;
    }

    @Override
    public void beforeTestExecution(ExtensionContext context) {
        ExtensionContext.Store store = this.getStore(context);
        store.put(START_TIME, System.currentTimeMillis());
    }

    @Override
    public void afterTestExecution(ExtensionContext context) throws Exception {
        ExtensionContext.Store store = this.getStore(context);
        long duration = System.currentTimeMillis() - store.remove(START_TIME, long.class);

        if (duration > threshold) {
            System.out.println("over threshold");
        }
    }

    private ExtensionContext.Store getStore(ExtensionContext context) {
        String testClassName = context.getRequiredTestClass().getName();
        String testMethodName = context.getRequiredTestMethod().getName();
        return context.getStore(ExtensionContext.Namespace.create(testClassName, testMethodName));
    }

}

profile ๋ณ„๋กœ ํŠน์ • ํƒœ๊ทธ๋งŒ ๋‹ฌ๋ ค์žˆ๋Š” @Test ๋งŒ ์‹คํ–‰๋˜๋„๋ก ํ•˜๋Š” ๋ฐฉ๋ฒ•. ๊ฐ•์˜์—์„œ๋Š” ์„ ๋‹ค๋ค˜๊ณ  gradle์€ ์ฐพ์•„๋ณด์•„์•ผ ํ•œ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•ด ๋ฐฐํฌ ํ™˜๊ฒฝ์—์„œ ๋นŒ๋“œ์‹œ ํŠน์ • ํƒœ๊ทธ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ์„ค์ •ํ•ด๋‘๊ณ  ํ•˜๋‚˜๋ผ๋„ ์‹คํŒจํ•œ๋‹ค๋ฉด ์ด๋ฅผ ๋ฐฐํฌํ•˜์ง€ ์•Š๋„๋ก ํ•˜๋Š” ์ „๋žต์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

JUnit 4์˜ ํ™•์žฅ ๋ชจ๋ธ์€ @RunWith(Runner), TestRule, MethodRule. ์€ ๋‹จ ํ•˜๋‚˜, Extension.

maven-surefile-plugin
JUnit 5์˜ ํ™•์žฅ ๋ชจ๋ธ