Skip to content

๐Ÿš‡ ์ง€ํ•˜์ฒ  ๊ฒฝ๋กœ ์กฐํšŒ - TDD ๋ฏธ์…˜์„ ์ง„ํ–‰ํ•˜๋Š” Repository

Notifications You must be signed in to change notification settings

lxxjn0/atdd-subway-path

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

57 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿš‡ atdd-subway-path

์ง€ํ•˜์ฒ  ๊ฒฝ๋กœ ์กฐํšŒ - TDD ๋ฏธ์…˜์„ ์ง„ํ–‰ํ•˜๋Š” Repository


์‹ค์Šต - ์ง€ํ•˜์ฒ  ๋…ธ์„ ๋„ ์กฐํšŒ

์š”๊ตฌ์‚ฌํ•ญ

  • ๋ชจ๋“  ์ง€ํ•˜์ฒ  ๋…ธ์„ ๊ณผ ๊ฐ ๋…ธ์„ ์— ํฌํ•จ๋œ ์ง€ํ•˜์ฒ ์—ญ ์กฐํšŒ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ์™€ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑ (Outside-In)
  • ํŽ˜์ด์ง€ ์—ฐ๋™

๊ธฐ๋Šฅ ๋ชฉ๋ก

์ง€ํ•˜์ฒ  ๋…ธ์„ ๋„ ํŽ˜์ด์ง€ ์กฐํšŒ

  • ๋ชจ๋“  ์ง€ํ•˜์ฒ  ๋…ธ์„ ๊ณผ ์ง€ํ•˜์ฒ ์—ญ ๋ชฉ๋ก์„ ์กฐํšŒ

์‹œ๋‚˜๋ฆฌ์˜ค

Feature: ์ „์ฒด ์ง€ํ•˜์ฒ  ๋…ธ์„ ๋„ ์ •๋ณด ์กฐํšŒ

  Scenario: ์ง€ํ•˜์ฒ  ๋…ธ์„ ๋„ ์ •๋ณด ์กฐํšŒ๋ฅผ ํ•œ๋‹ค.
    Given ์ง€ํ•˜์ฒ ์—ญ์ด ์—ฌ๋Ÿฌ ๊ฐœ ์ถ”๊ฐ€๋˜์–ด์žˆ๋‹ค.
    And ์ง€ํ•˜์ฒ  ๋…ธ์„ ์ด ์—ฌ๋Ÿฌ ๊ฐœ ์ถ”๊ฐ€๋˜์–ด์žˆ๋‹ค.
    And ์ง€ํ•˜์ฒ  ๋…ธ์„ ์— ์ง€ํ•˜์ฒ ์—ญ์ด ์—ฌ๋Ÿฌ ๊ฐœ ์ถ”๊ฐ€๋˜์–ด์žˆ๋‹ค.
    
    When ์ง€ํ•˜์ฒ  ๋…ธ์„ ๋„ ์ „์ฒด ์กฐํšŒ ์š”์ฒญ์„ ํ•œ๋‹ค.
    
    Then ์ง€ํ•˜์ฒ  ๋…ธ์„ ๋„ ์ „์ฒด๋ฅผ ์‘๋‹ต ๋ฐ›๋Š”๋‹ค.

์‹ค์Šต

๋ฏธ์…˜ ์ง„ํ–‰ ์ˆœ์„œ

  1. ์ธ์ˆ˜ ์กฐ๊ฑด ํŒŒ์•…ํ•˜๊ธฐ - fin
  2. ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ ์ž‘์„ฑํ•˜๊ธฐ - fin
  3. ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ ์„ฑ๊ณต ์‹œํ‚ค๊ธฐ - fin
  4. ๊ธฐ๋Šฅ ๊ตฌํ˜„ - fin
  5. API๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํŽ˜์ด์ง€ ์—ฐ๋™ํ•˜๊ธฐ - fin

๊ธฐ๋Šฅ ๊ตฌํ˜„ ์ˆœ์„œ - Outside In

  1. ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ
  2. Mock ์„œ๋ฒ„์™€ DTO ์ •์˜
  3. ์ปจํŠธ๋กค๋Ÿฌ ๊ตฌํ˜„
  4. ์„œ๋น„์Šค ๊ตฌํ˜„ - TDD๋กœ ์ง„ํ–‰
  5. ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ ๊ฒ€์ฆ ํ›„ ํ™•์ธ

1๋‹จ๊ณ„ : ์บ์‹œ ์ ์šฉ

์š”๊ตฌ ์‚ฌํ•ญ

HTTP ์บ์‹œ ์ ์šฉํ•˜๊ธฐ

  • HTTP Cache์˜ ์ข…๋ฅ˜๋ฅผ ํ•™์Šต - fin
  • ์ง€ํ•˜์ฒ  ๋…ธ์„ ๋„ ์กฐํšŒ์‹œ ETag๋ฅผ ํ†ตํ•ด ์บ์‹œ๋ฅผ ์ ์šฉ - fin
  • LineControllerTest์˜ ETag ํ…Œ์ŠคํŠธ๋ฅผ ์„ฑ๊ณต์‹œํ‚ค๊ธฐ - fin

์ถ”๊ฐ€๋กœ ์ƒ๊ฐํ•ด๋ณด๊ธฐ

์„œ๋ฒ„ ์บ์‹œ ์ ์šฉ

  • ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด์„œ๋Š” ์„œ๋ฒ„์ชฝ์—๋„ ์บ์‹œ ์„ค์ •์ด ํ•„์š”
  • ์•„๋ž˜์˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ 

2๋‹จ๊ณ„ : ์ง€ํ•˜์ฒ  ๊ฒฝ๋กœ ์กฐํšŒ 1

์š”๊ตฌ์‚ฌํ•ญ

  • ์ถœ๋ฐœ์—ญ๊ณผ ๋„์ฐฉ์—ญ์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋Šฅ ๊ตฌํ˜„(Happy Case)์„ ๋ชฉํ‘œ๋กœ ํ•˜๊ณ  ์˜ˆ์™ธ ์ƒํ™ฉ(Side Case)์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋Š” ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ ๊ณ ๋ ค
  • TDD ํ”„๋กœ์„ธ์Šค๋ฅผ ๋”ฐ๋ผ์„œ ๊ฐœ๋ฐœ ์ง„ํ–‰
  • ์ธ์ˆ˜ ์กฐ๊ฑด & ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ
  • ๊ธฐ๋Šฅ ๊ตฌํ˜„์‹œ ํ•„์š”ํ•œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ
  • ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ์ œ๊ฑฐ(ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ค‘๋ณต ์ œ๊ฑฐ)
  • ๊ฐ์ฒด์ง€ํ–ฅ ์ƒํ™œ์ฒด์กฐ ์ค€์ˆ˜

๊ธฐ๋Šฅ ๋ชฉ๋ก

๊ฒฝ๋กœ ์กฐํšŒ API

  • ์ถœ๋ฐœ์—ญ๊ณผ ๋„์ฐฉ์—ญ์„ ์ž…๋ ฅ
  • ์ตœ๋‹จ ๊ฑฐ๋ฆฌ ๊ธฐ์ค€์œผ๋กœ ๊ฒฝ๋กœ์™€ ๊ธฐํƒ€ ์ •๋ณด๋ฅผ ์‘๋‹ต
    • ์ด ์†Œ์š”์‹œ๊ฐ„, ์ด ๊ฑฐ๋ฆฌ ๋“ฑ
  • ์ตœ๋‹จ ๊ฒฝ๋กœ๊ฐ€ ํ•˜๋‚˜๊ฐ€ ์•„๋‹ ๊ฒฝ์šฐ ์–ด๋Š ๊ฒฝ๋กœ๋“  ํ•˜๋‚˜๋งŒ ์‘๋‹ต

๊ฒฝ๋กœ ์กฐํšŒ ํ™”๋ฉด

  • ์ถœ๋ฐœ์—ญ๊ณผ ๋„์ฐฉ์—ญ์˜ ๊ฒฝ๋กœ ์ •๋ณด ๋…ธ์ถœ
    • ์ด ์†Œ์š”์‹œ๊ฐ„, ์ •์ฐจ์—ญ ๋“ฑ
  • ์ฆ๊ฒจ์ฐพ๊ธฐ ๋ฒ„ํŠผ๊ณผ ์ตœ์†Œ ์‹œ๊ฐ„ ๊ธฐ์ค€ ์กฐํšŒ๋Š” ๋‹ค๋ฅธ ๋ฏธ์…˜์ด๋ฏ€๋กœ ๋ฌด์‹œ
    • ์ตœ์†Œ์‹œ๊ฐ„ ๊ธฐ์ค€์€ 3๋‹จ๊ณ„ ๋ฏธ์…˜
    • ์ฆ๊ฒจ์ฐพ๊ธฐ(๋ณ„)์€ 3์ฃผ์ฐจ ๋ฏธ์…˜

๋ฏธ์…˜ ์ˆ˜ํ–‰ ์ˆœ์„œ

  1. ์ธ์ˆ˜ ์กฐ๊ฑด ์ž‘์„ฑ ๋ฐ ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ ์ž‘์„ฑํ•˜๊ธฐ

    • Gherkin ๋ฌธ๋ฒ•์„ ํ™œ์šฉํ•˜์—ฌ ์ธ์ˆ˜ ์กฐ๊ฑด ์ž‘์„ฑ

    https://cucumber.io/docs/gherkin/reference

  2. ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ ์„ฑ๊ณต ์‹œํ‚ค๊ธฐ

    • mock ์„œ๋ฒ„์™€ dto๋ฅผ ์ •์˜ํ•˜์—ฌ ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ ์„ฑ๊ณต ์‹œํ‚ค๊ธฐ
  3. ๊ธฐ๋Šฅ ๊ตฌํ˜„

    • ์ปจํŠธ๋กค๋Ÿฌ ๋ ˆ์ด์–ด ๊ตฌํ˜„ ์ดํ›„ ์„œ๋น„์Šค ๋ ˆ์ด์–ด ๊ตฌํ˜„ ์‹œ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ ์šฐ์„  ์ž‘์„ฑ ํ›„ ๊ธฐ๋Šฅ ๊ตฌํ˜„
    • ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ ๋‚ด๋ถ€์—์„œ ๋„๋ฉ”์ธ๋“ค๊ฐ„์˜ ๋กœ์ง์˜ ํ๋ฆ„์„ ๊ฒ€์ฆ, ์ด ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ๋„๋ฉ”์ธ์€ mock ๊ฐ์ฒด๋ฅผ ํ™œ์šฉ
    • ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•œ ๋กœ์ง์„ ๊ฒ€์ฆํ•  ๋•Œ๋Š” ๊ฐ€๊ธ‰์  ์‹ค์ œ ๊ฐ์ฒด๋ฅผ ํ™œ์šฉ
    • Happy ์ผ€์ด์Šค์— ๋Œ€ํ•œ ๋ถ€๋ถ„๋งŒ ๊ตฌํ˜„(Side ์ผ€์ด์Šค์— ๋Œ€ํ•œ ๊ตฌํ˜„์€ ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ ์ง„ํ–‰)
  4. API๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํŽ˜์ด์ง€ ์—ฐ๋™ํ•˜๊ธฐ

    • ์ •์ƒ์ ์ธ ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ ์šฐ์„  ์ ์šฉ

์ตœ๋‹จ ๊ฒฝ๋กœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • jgrapht ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๊ฐ„ํŽธํ•˜๊ฒŒ ์ตœ๋‹จ๊ฑฐ๋ฆฌ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Œ
  • ์ •์ (vertext)๊ณผ ๊ฐ„์„ (edge), ๊ทธ๋ฆฌ๊ณ  ๊ฐ€์ค‘์น˜ ๊ฐœ๋…์„ ์ด์šฉ
    • ์ •์ : ์ง€ํ•˜์ฒ ์—ญ(Station)
    • ๊ฐ„์„ : ์ง€ํ•˜์ฒ ์—ญ ์—ฐ๊ฒฐ์ •๋ณด(LineStaion)
    • ๊ฐ€์ค‘์น˜: ๊ฑฐ๋ฆฌ or ์†Œ์š”์‹œ๊ฐ„
  • ์ตœ๋‹จ ๊ฑฐ๋ฆฌ ๊ธฐ์ค€ ์กฐํšŒ ์‹œ ๊ฐ€์ค‘์น˜๋ฅผ ๊ฑฐ๋ฆฌ๋กœ ์„ค์ •
@Test
public void getDijkstraShortestPath() {
    WeightedMultigraph<String, DefaultWeightedEdge> graph
            = new WeightedMultigraph(DefaultWeightedEdge.class);
    graph.addVertex("v1");
    graph.addVertex("v2");
    graph.addVertex("v3");
    graph.setEdgeWeight(graph.addEdge("v1", "v2"), 2);
    graph.setEdgeWeight(graph.addEdge("v2", "v3"), 2);
    graph.setEdgeWeight(graph.addEdge("v1", "v3"), 100);

    DijkstraShortestPath dijkstraShortestPath
            = new DijkstraShortestPath(graph);
    List<String> shortestPath 
            = dijkstraShortestPath.getPath("v3", "v1").getVertexList();

    assertThat(shortestPath.size()).isEqualTo(3);
}

jgrapht graph-algorithms

์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ…Œ์ŠคํŠธ

  • ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๊ตฌํ˜„์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜์ง€ ์•Š์Œ
  • ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋Š” ๋กœ์ง์„ ๊ฒ€์ฆํ•ด์•ผ ํ•จ
  • ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋Š” ๋กœ์ง ๊ฒ€์ฆ ์‹œ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ถ€๋ถ„์€ ์‹ค์ œ ๊ฐ์ฒด๋ฅผ ํ™œ์šฉ

3๋‹จ๊ณ„ - ์ง€ํ•˜์ฒ  ๊ฒฝ๋กœ ์กฐํšŒ 2

์˜ˆ์™ธ์ฒ˜๋ฆฌ ๋ฐ Side ์ผ€์ด์Šค

์š”๊ตฌ์‚ฌํ•ญ

  • Happy ์ผ€์ด์Šค ์ด์™ธ ์˜ˆ์™ธ ์ƒํ™ฉ์— ๋Œ€ํ•œ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ์ถœ๋ฐœ์—ญ๊ณผ ๋„์ฐฉ์—ญ์ด ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์ง€ ์•Š์€ ๊ฒฝ์šฐ ๊ฒ€์ฆ

4๋‹จ๊ณ„ - ์ง€ํ•˜์ฒ  ๊ฒฝ๋กœ ์กฐํšŒ 3

์š”๊ตฌ์‚ฌํ•ญ

  • ์ตœ์†Œ ์‹œ๊ฐ„ ๊ฒฝ๋กœ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€
  • ์ตœ๋‹จ ๊ฒฝ๋กœ ์กฐํšŒ ๊ธฐ๋Šฅ๊ณผ์˜ ์ฝ”๋“œ ์ค‘๋ณต ์ œ๊ฑฐ(ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ํฌํ•จ)

๋ฆฌํŒฉํ† ๋ง

1์ฐจ ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜

  • Bean์œผ๋กœ ์ฃผ์ž…๋ฐ›๋Š” ๋ณ€์ˆ˜๋“ค final๋กœ ์ˆ˜์ •
  • PathController์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ (side case๋„ ํ•จ๊ป˜)
  • Enum์œผ๋กœ PathType ๊ตฌํ˜„ ํ›„ ๋ฆฌํŒฉํ† ๋ง
  • PathAcceptanceTest๋ฅผ ParameterizedTest๋กœ ์ˆ˜์ •ํ•ด๋ณด๊ธฐ
  • PathService์— DijkstraShortestPath.findPathBetween() ๋ฉ”์„œ๋“œ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„ ์ฐพ์•„๋ณด๊ธฐ
  • ๊ฒฝ๋กœ ๊ฒ€์ƒ‰์‹œ css๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„ ์ˆ˜์ •

2์ฐจ ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜

  • PathController ์˜ searchPath ๋ฉ”์„œ๋“œ์˜ RequestParam ์„ ์ปค๋งจ๋“œ ๊ฐ์ฒด(RequestDto)๋กœ ๋ณ€๊ฒฝ ๋ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ

    • Dto์˜ ๋ณ€์ˆ˜๋กœ type๋„ ํ•จ๊ป˜ ์ €์žฅํ•˜๋„๋ก ์ˆ˜์ •
  • FrontEnd ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ ์ˆ˜์ •

    • service์˜ index.js ์ˆ˜์ •(query๋กœ type๋„ ํ•จ๊ป˜ ๋„˜๊ธฐ๋„๋ก)
    • search.js์˜ ๊ฒฝ๋กœ ์กฐํšŒ ํ•จ์ˆ˜ ์ˆ˜์ •
    • ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์—ญ์„ ์ž…๋ ฅํ•  ์‹œ Front์—์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์ˆ˜์ •
  • ์ตœ๋‹จ๊ฑฐ๋ฆฌ, ์ตœ์†Œ์‹œ๊ฐ„์— ๋Œ€ํ•œ ์กฐํšŒ ๊ฒฐ๊ณผ๋ฅผ ํ•œ ๋ฒˆ์— ๋ณด๋‚ด์ง€ ๋ง๊ณ  ์š”์ฒญ๋งˆ๋‹ค ์ „๋‹ฌํ•˜๋„๋ก ์ˆ˜์ •(์บ์‹ฑ ์ ์šฉ์ด ํ•„์š”)

  • ์ถœ๋ฐœ์—ญ๊ณผ ๋„์ฐฉ์—ญ์ด ๊ฐ™์€ ๊ฒฝ์šฐ, ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ถœ๋ฐœ์—ญ์— ๋Œ€ํ•œ ์กฐํšŒ ์š”์ฒญ์ด ์ด๋ฃจ์–ด์งˆ ๊ฒฝ์šฐ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ž‘์„ฑ

About

๐Ÿš‡ ์ง€ํ•˜์ฒ  ๊ฒฝ๋กœ ์กฐํšŒ - TDD ๋ฏธ์…˜์„ ์ง„ํ–‰ํ•˜๋Š” Repository

Topics

Resources

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •