æ°ãããããžã§ã¯ãã«æ¥ãŠãç§ã¯å®æçã«æ¬¡ã®ããããã®ç¶æ³ã«ééããŸãã
- ãã¹ãã¯ãŸã£ãããããŸããã
- ãã¹ãã¯ã»ãšãã©ãããŸããããã»ãšãã©æžãããŠããããç¶ç¶çã«å®è¡ãããŸããã
- ãã¹ãã¯ååšããCIïŒç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³ïŒã«å«ãŸããŠããŸãããè¯ãããšããã害ã倧ãããªããŸãã
æ®å¿µãªãããé©åãªã¹ãã«ããªãå Žåã«ãã¹ãã®å®è£ ãéå§ããããšããæ·±å»ãªè©Šã¿ã«ã€ãªããã®ã¯ãåŸè ã®ã·ããªãªã§ãã
çŸåšã®ç¶æ³ãå€ããããã«äœãã§ããŸããïŒ ãã¹ãã䜿çšãããšããèãæ¹ã¯æ°ãããã®ã§ã¯ãããŸããã åæã«ãã»ãšãã©ã®ãã¥ãŒããªã¢ã«ã¯ããã¯ããŠãæãæ¹æ³ã«ã€ããŠã®æåãªå³ã«äŒŒãŠããŸãïŒJUnitãæ¥ç¶ããæåã®ãã¹ããäœæããæåã®ã¢ãã¯ã䜿çšããŠå®è¡ããŠãã ããïŒ ãã®ãããªèšäºã¯ãã©ã®ãã¹ããæžãå¿ èŠãããããäœã«æ³šæãæã䟡å€ããããããããŠããããã¹ãŠãã©ã®ããã«çãããã«ã€ããŠã®è³ªåã«ã¯çããŸããã ããããããã®èšäºã®ã¢ã€ãã¢ãçãŸããŸããã 誰ã«ãšã£ãŠããã®éãä¿é²ããããã«ãããŸããŸãªãããžã§ã¯ãã§ãã¹ããå®è£ ããçµéšãç°¡åã«èŠçŽããããšããŸããã
ãã®ãããã¯ã«é¢ããå ¥éèšäºã¯ååã«ãããããç¹°ãè¿ã説æããããšã¯ãããå察åŽããè¡ãããšããŸããã æåã®éšåã§ã¯ããã¹ãã«ã¯è¿œå ã³ã¹ãã®ã¿ã䌎ããšããç¥è©±ãèŠããŸãã å質ãã¹ãã®äœæãéçºããã»ã¹ãå éããæ¹æ³ã瀺ãããŸãã 次ã«ãå°èŠæš¡ãããžã§ã¯ãã®äŸã§ããã®ã¡ãªãããå®çŸããããã«åŸãã¹ãåºæ¬ååãšã«ãŒã«ãæ€èšããŸãã æåŸã«ãæåŸã®ã»ã¯ã·ã§ã³ã§ã¯ãå ·äœçãªå®è£ ã®æšå¥šäºé ã瀺ããŸãããã¹ããéå§ãããšãã«å žåçãªåé¡ãåé¿ããæ¹æ³ãšã¯å¯Ÿç §çã«ãéçºãå€§å¹ ã«é ãããŸãã
ç§ã®äž»ãªå°éåéã¯Javaããã¯ãšã³ãã§ãããããäŸã§ã¯æ¬¡ã®ãã¯ãããžãŒã¹ã¿ãã¯ã䜿çšãããŸãïŒJavaãJUnitãH2ãMockitoãSpringãHibernateã ããã«ããã®èšäºã®å€§éšåã¯äžè¬çãªãã¹ãã®åé¡ã«åœãŠãããŠããããã®äžã®ãã³ãã¯ããåºç¯ãªã¿ã¹ã¯ã«é©çšã§ããŸãã
ãã ãã泚æããŠãã ããïŒ ãã¹ãã¯éåžžã«äžæ¯æ§ããããŸãããã¹ãã®äœ¿çšæ¹æ³ãåŠã¶ãšããã¹ããªãã§ã¯çããããªããªããŸãã
å
容
ãã¹ããšéçºé床
ãã¹ãã®å®è£ ãè°è«ããéã«çããäž»ãªè³ªåïŒãã¹ããæžãã®ã«ã©ããããæéãããããã©ã®ãããªå©ç¹ããããŸããïŒ ãã¹ãã¯ãä»ã®æè¡ãšåæ§ã«ãéçºãšå®è£ ã«çå£ã«åãçµãå¿ èŠããããããæåã¯å€§ããªã¡ãªããã¯æåŸ ã§ããŸããã æéã³ã¹ãã«ã€ããŠã¯ãç¹å®ã®ããŒã ã«å€§ããäŸåããŠããŸãã ãã ããã³ãŒãã£ã³ã°ã®è¿œå ã³ã¹ãã®20ã30ïŒ æªæºãæ£ç¢ºã«èšç®ããªãã§ãã ããã å°ãªããŠããå°ãªããšãäœããã®çµæãéæããã«ã¯ååã§ã¯ãããŸããã å€ãã®å Žåããã¹ããæçšã«ãªãåã§ãã£ãŠãããã®ã¢ã¯ãã£ããã£ãåæžããäž»ãªçç±ã¯ãå³æè¿åã®æåŸ ã§ãã
ããããã©ã®ãããªå¹çã«ã€ããŠè©±ããŠããã®ã§ããããïŒ å®è£ ã®é£ããã«ã€ããŠæè©ãããããããŠãæéãã¹ããç¯çŽããå ·äœçãªæ©äŒãã©ã®ããã«éãããããèŠãŠã¿ãŸãããã
ã©ãã§ãã³ãŒããå®è¡ãã
ãããžã§ã¯ãã«ãã¹ãããªãå Žåãéå§ããå¯äžã®æ¹æ³ã¯ãã¢ããªã±ãŒã·ã§ã³å šäœã解é€ããããšã§ãã çŽ15ã20ç§ããããŸãããå®å šãªèµ·åã«æ°åãããããšããã倧èŠæš¡ãªãããžã§ã¯ãã®å Žåã¯ãã£ãã«ãããŸããã ããã¯éçºè ã«ãšã£ãŠäœãæå³ããŸããïŒ åœŒãã®äœæ¥æéã®éèŠãªéšåã¯ããããã®çãåŸ æ©ã»ãã·ã§ã³ã§ããããã®éãçŸåšã®ã¿ã¹ã¯ã§äœæ¥ãç¶ããããšã¯ã§ããŸããããåæã«ä»ã®äœãã«åãæ¿ããæéã¯çãããŸãã å€ãã®äººã¯ãä¿®æ£ãšä¿®æ£ã®éã®é·ãåèµ·åã®ããã«1æéã§æžãããã³ãŒããäœæéãã®ãããã°ãå¿ èŠãšãããããªãããžã§ã¯ãã«å°ãªããšãäžåºŠééããŸããã ãã¹ãã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã®å°ããªéšåã®å®è¡ã«å¶éããããšãã§ããŸããããã«ãããåŸ ã¡æéãå€§å¹ ã«ççž®ãããã³ãŒãã®äœæ¥ã®çç£æ§ãåäžããŸãã
ããã«ãä»»æã®å Žæã§ã³ãŒããå®è¡ã§ããããããã培åºçãªãããã°ãå¯èœã«ãªããŸãã å€ãã®å Žåãã¢ããªã±ãŒã·ã§ã³ã€ã³ã¿ãŒãã§ãŒã¹ãä»ããŠäž»ãªè¯å®çãªãŠãŒã¹ã±ãŒã¹ããã§ãã¯ããå Žåã§ããå€å€§ãªåŽåãšæéãå¿ èŠã§ãã ãã¹ãã®ååšã«ãããç¹å®ã®æ©èœã®è©³çŽ°ãªãã§ãã¯ãã¯ããã«ç°¡åãã€è¿ éã«è¡ãããšãã§ããŸãã
å¥ã®ãã©ã¹ã¯ããã¹ãããããŠãããã®ãµã€ãºãå¶åŸ¡ããæ©èœã§ãã ãã¹ãããããžãã¯ã®è€éãã«å¿ããŠãã¢ããªã±ãŒã·ã§ã³å šäœã®ãã¹ãã®èªååãŸã§ã1ã€ã®ã¡ãœãããã¯ã©ã¹ãæ©èœãå®è£ ããã¯ã©ã¹ã®ã°ã«ãŒãããµãŒãã¹ãªã©ã«å¶éããããšãã§ããŸãã ãã®æè»æ§ã«ãããäœã¬ãã«ã§ãã¹ãããããããå€ãã®è©³çŽ°ããé«ã¬ãã«ã®ãã¹ãããªãããŒãã§ããŸãã
ãã¹ãã®åèµ·å
ãã®ãã©ã¹ã¯ãã¹ãèªååã®æ¬è³ªãšããŠããåŒçšãããŸãããããŸã銎æã¿ã®ãªãè§åºŠããèŠãŠã¿ãŸãããã éçºè ã«ãšã£ãŠã©ã®ãããªæ°ããæ©äŒãéãããŸããïŒ
ãŸãããããžã§ã¯ãã«åå ããæ°ããéçºè ã¯ãæ¢åã®ãã¹ããç°¡åã«å®è¡ããŠãäŸã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ã®ããžãã¯ãç解ã§ããŸãã æ®å¿µãªãããããã®éèŠæ§ã¯éåžžã«éå°è©äŸ¡ãããŠããŸãã çŸä»£ã®ç¶æ³ã§ã¯ãåã人ã1ã2幎以äžãããžã§ã¯ãã«åãçµãããšã¯ãã£ãã«ãããŸããã ãŸããããŒã ã¯æ°äººã§æ§æãããŠããããã2ã3ãæããšã«æ°ããåå è ãçŸããã®ã¯ãæ¯èŒç倧èŠæš¡ãªãããžã§ã¯ãã®å žåçãªç¶æ³ã§ãã ç¹ã«é£ãããããžã§ã¯ãã¯ãéçºè ã®äžä»£å šäœã®ã·ãããåããŠããŸãïŒ ã¢ããªã±ãŒã·ã§ã³ã®ä»»æã®éšåãç°¡åã«èµ·åããæã ã·ã¹ãã ã®åäœã確èªã§ãããããæ°ããããã°ã©ããŒããããžã§ã¯ãã«æ²¡é ããã®ãç°¡åã«ãªããŸãã ããã«ãã³ãŒãããžãã¯ã®ãã詳现ãªèª¿æ»ã«ãããåºåã§çºçãããšã©ãŒã®æ°ãšãå°æ¥ãšã©ãŒããããã°ããæéãççž®ã§ããŸãã
第äºã«ãã¢ããªã±ãŒã·ã§ã³ãæ£åžžã«åäœããŠããããšãç°¡åã«ç¢ºèªã§ãããããç¶ç¶çãªãã¡ã¯ã¿ãªã³ã°ã®éãéãããŸãã æ®å¿µãªããããã®çšèªã¯CIãããã¯ããã«äººæ°ããããŸããã ããã¯ããã¹ãŠã®ã³ãŒããæ¹è¯ããããšã§ãªãã¡ã¯ã¿ãªã³ã°ãå®è¡ã§ããããšãæå³ããŸãã ã³ãŒãããŒã¹ã®å£åãåé¿ãããããžã§ã¯ãã«é·ã幞ããªç掻ãä¿èšŒããã®ã¯ãæªåé«ãã¹ã«ãŠãã«ãŒã«ãå°çåãããé§è»å Žãæž æœã«ä¿ã€ããå®æçã«éµå®ããããšã§ãã
ãããã°
ãããã°ã«ã€ããŠã¯ãåã®æ®µèœã§æ¢ã«èª¬æããŸãããããã®ç¹ã¯éåžžã«éèŠã§ããããã詳ããèŠãå¿ èŠããããŸãã æ®å¿µãªãããã³ãŒãã®äœæãšãããã°ã«è²»ããããæéã®é¢ä¿ã枬å®ããä¿¡é Œã§ããæ¹æ³ã¯ãããŸããããããã®ããã»ã¹ã¯å®éã«ã¯äºãã«åãé¢ããªãããã§ãã ããã§ãããããžã§ã¯ãã§å質ãã¹ãã䜿çšã§ãããšããããã¬ãŒãå®è¡ããå¿ èŠãã»ãšãã©ãªããªããŸã§ããããã°æéãå€§å¹ ã«ççž®ãããŸãã
æå¹æ§
äžèšã®ãã¹ãŠã«ãããã³ãŒãã®åæãããã°ã®æéãå€§å¹ ã«ç¯çŽã§ããŸãã é©åãªã¢ãããŒãã䜿çšãããšãããã ãã§ãã¹ãŠã®è¿œå ã®éçºã³ã¹ããååãããŸãã æ®ãã®ãã¹ãããŒãã¹-ã³ãŒãããŒã¹ã®å質ã®æ¹åïŒèšèšãäžååãªã³ãŒãã¯ãã¹ããå°é£ã§ãïŒãæ¬ é¥ã®æ°ã®åæžããã€ã§ãã³ãŒãã®æ£ç¢ºæ§ãæ€èšŒããæ©èœãªã©-ã¯ã»ãŒç¡æã«ãªããŸãã
çè«ããå®è·µãž
èšèã§ã¯ãããã¯ãã¹ãŠè¯ãããã«èŠããŸãããããžãã¹ã«åãæãããŸãããã åè¿°ããããã«ããã¹ãç°å¢ã®åæã»ããã¢ããã®äœææ¹æ³ã«ã€ããŠã¯ãååãªè³æããããŸãã ãããã£ãŠãããã«å®æãããããžã§ã¯ãã«é²ã¿ãŸãã ãœãŒã¹ã¯ãã¡ãã
ææŠãã
ãã³ãã¬ãŒãã¿ã¹ã¯ãšããŠããªã³ã©ã€ã³ã¹ãã¢ã®ããã¯ãšã³ãã®å°ããªãã©ã°ã¡ã³ããèããŸãã 補åãæäœããããã®å žåçãªAPIãäœæããŸãïŒäœæãåä¿¡ãç·šéã ã¯ã©ã€ã¢ã³ããšé£æºããããã®ããã€ãã®æ¹æ³ïŒããæ°ã«å ¥ãã®è£œåããå€æŽãã泚æã®ããŒãã¹ãã€ã³ããèšç®ããŸãã
ãã¡ã€ã³ã¢ãã«
äŸããªãŒããŒããŒãããªãããã«ããã£ãŒã«ããšã¯ã©ã¹ã®æå°éã®ã»ããã«å¶éããŸãã
顧客ã«ã¯ããŠãŒã¶ãŒåããæ°ã«å ¥ãã®è£œåãžã®ãªã³ã¯ããã¬ãã¢ã 顧客ãã©ããã瀺ããã©ã°ããããŸãã
補åïŒè£œåïŒ-ååãäŸ¡æ Œãå²åŒãããã³çŸåšåºåãããŠãããã©ããã瀺ããã©ã°ã
ãããžã§ã¯ãæ§é
ã¡ã€ã³ãããžã§ã¯ãã³ãŒãã®æ§é ã¯æ¬¡ã®ãšããã§ãã
ã¯ã©ã¹ã¯éå±€åãããŠããŸãïŒ
- ã¢ãã«-ãããžã§ã¯ãã®ãã¡ã€ã³ã¢ãã«ã
- Jpa-Spring Dataã«åºã¥ããŠããŒã¿ããŒã¹ãæäœããããã®ãªããžããªã
- ãµãŒãã¹-ã¢ããªã±ãŒã·ã§ã³ã®ããžãã¹ããžãã¯ã
- ã³ã³ãããŒã©ãŒ-APIãå®è£ ããã³ã³ãããŒã©ãŒã
åäœãã¹ãæ§é ã
ãã¹ãã¯ã©ã¹ã¯ãå ã®ã³ãŒããšåãããã±ãŒãžã«å«ãŸããŠããŸãã ããã«ããã¹ãããŒã¿ãæºåããããã®ãã«ããŒãå«ãããã±ãŒãžãäœæãããŸãããããã®è©³çŽ°ã«ã€ããŠã¯ä»¥äžãåç §ããŠãã ããã
åäœãã¹ããšçµ±åãã¹ããåé¢ãããšäŸ¿å©ã§ãã å€ãã®å Žåããããã«ã¯ç°ãªãäŸåé¢ä¿ããããå¿«é©ãªéçºã®ããã«ãã©ã¡ããäžæ¹ãå®è¡ããæ©èœãå¿ èŠã§ãã ããã¯ããŸããŸãªæ¹æ³ã§å®çŸã§ããŸãïŒåœåèŠåãã¢ãžã¥ãŒã«ãããã±ãŒãžãsourceSetsã ç¹å®ã®æ¹æ³ã®éžæã¯ãã£ã±ã奜ã¿ã®åé¡ã§ãã ãã®ãããžã§ã¯ãã§ã¯ãçµ±åãã¹ãã¯å¥ã®sourceSet-integrationTestã«ãããŸãã
åäœãã¹ããšåæ§ã«ãçµ±åãã¹ããå«ãã¯ã©ã¹ã¯å ã®ã³ãŒããšåãããã±ãŒãžã«å«ãŸããŠããŸãã ããã«ãæ§æã®éè€ãåãé€ãã®ã«åœ¹ç«ã€åºæ¬ã¯ã©ã¹ããããå¿ èŠã«å¿ããŠäŸ¿å©ãªæ±çšã¡ãœãããå«ãŸããŠããŸãã
çµ±åãã¹ã
éå§ãã䟡å€ã®ãããã¹ãã«ã¯ããŸããŸãªã¢ãããŒãããããŸãã ãã¹ãæžã¿ã®ããžãã¯ãããã»ã©è€éã§ãªãå Žåã¯ãããã«çµ±åããžãã¯ã«é²ãããšãã§ããŸãïŒåãå ¥ãããžãã¯ãšãåŒã°ããŸãïŒã åäœãã¹ããšã¯ç°ãªããã¢ããªã±ãŒã·ã§ã³å šäœãæ£ããåäœããããšã確èªããŸãã
建ç¯
ãŸããã©ã®ç¹å®ã¬ãã«ã§çµ±åãã§ãã¯ãå®è¡ãããã決å®ããå¿ èŠããããŸãã Spring Bootã¯å®å šãªéžæã®èªç±ãæäŸããŸããã³ã³ããã¹ãã®äžéšãã³ã³ããã¹ãå šäœãããã«ã¯ãã¹ãããã¢ã¯ã»ã¹å¯èœãªæ¬æ ŒçãªãµãŒããŒãŸã§äžããããšãã§ããŸãã ã¢ããªã±ãŒã·ã§ã³ã®ãµã€ãºã倧ãããªããšããã®åé¡ã¯ãŸããŸãè€éã«ãªããŸãã å€ãã®å Žåãç°ãªãã¬ãã«ã§ç°ãªããã¹ããäœæããå¿ èŠããããŸãã
é©åãªéå§ç¹ã¯ããµãŒããŒãèµ·åããã«ã³ã³ãããŒã©ãŒããã¹ãããããšã§ãã æ¯èŒçå°ããªã¢ããªã±ãŒã·ã§ã³ã§ã¯ãããã©ã«ãã§ãã¹ãéã§åå©çšãããäžåºŠã ãåæåããããããã³ã³ããã¹ãå šäœãäžããããšã¯éåžžã«èš±å®¹ãããŸãã
ProductController
ã¯ã©ã¹ã®åºæ¬ã¡ãœãããæ€èšããŠãã ããã
@PostMapping("new") public Product createProduct(@RequestBody Product product) { return productService.createProduct(product); } @GetMapping("{productId}") public Product getProduct(@PathVariable("productId") long productId) { return productService.getProduct(productId); } @PostMapping("{productId}/edit") public void updateProduct(@PathVariable("productId") long productId, @RequestBody Product product) { productService.updateProduct(productId, product); }
ãšã©ãŒåŠçã®åé¡ã¯æ®ãããŠããŸãã ã¹ããŒãããäŸå€ã®åæã«åºã¥ããŠå€éšçã«å®è£ ãããŠãããšä»®å®ããŸãã ã¡ãœããã®ã³ãŒãã¯éåžžã«åçŽã§ããã
ProductService
å®è£ ã¯ããã»ã©è€éã§
ProductService
ãŸããã
@Transactional(readOnly = true) public Product getProduct(Long productId) { return productRepository.findById(productId) .orElseThrow(() -> new DataNotFoundException("Product", productId)); } @Transactional public Product createProduct(Product product) { return productRepository.save(new Product(product)); } @Transactional public Product updateProduct(Long productId, Product product) { Product dbProduct = productRepository.findById(productId) .orElseThrow(() -> new DataNotFoundException("Product", productId)); dbProduct.setPrice(product.getPrice()); dbProduct.setDiscount(product.getDiscount()); dbProduct.setName(product.getName()); dbProduct.setIsAdvertised(product.isAdvertised()); return productRepository.save(dbProduct); }
ProductRepository
ãªããžããªã«ã¯ãç¬èªã®ã¡ãœããããŸã£ããå«ãŸããŠããŸããã
public interface ProductRepository extends JpaRepository<Product, Long> { }
ãã§ãŒã³å šäœãè€æ°ã®çµ±åãã¹ãã§ç°¡åãã€å¹ççã«ãã§ãã¯ã§ããããããããã®ã¯ã©ã¹ã¯åäœãã¹ããå¿ èŠãšããªãããšããã¹ãŠç€ºåããŠããŸãã åããã¹ããç°ãªããã¹ãã«è€è£œãããšããããã°ãè€éã«ãªããŸãã ã³ãŒãã«ãšã©ãŒãçºçããå Žåããã¹ãã¯1ã€ã§ã¯ãªããäžåºŠã«10ã15ã«ãªããŸãã ããã«ã¯ãããã«åæãå¿ èŠã«ãªããŸãã éè€ããªãå Žåã倱æãããã¹ãã¯ãã ã¡ã«ãšã©ãŒã瀺ãå¯èœæ§ããããŸãã
æ§æ
䟿å®äžãSpringæ§æãšããã€ãã®ãã£ãŒã«ããå«ãåºæ¬ã¯ã©ã¹
BaseControllerIT
ã匷調衚瀺ããŸãã
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) @Transactional public abstract class BaseControllerIT { @Autowired protected ProductRepository productRepository; @Autowired protected CustomerRepository customerRepository; }
ãªããžããªã¯ããã¹ãã¯ã©ã¹ãä¹±éã«ãªããªãããã«åºæ¬ã¯ã©ã¹ã«ç§»åãããŸãã ãããã®åœ¹å²ã¯ãè£å©çãªãã®ã§ããããŒã¿ã®æºåãšãã³ã³ãããŒã©ãŒã®åäœåŸã®ããŒã¿ããŒã¹ã®ã¹ããŒã¿ã¹ã®ç¢ºèªã§ãã ã¢ããªã±ãŒã·ã§ã³ã®ãµã€ãºã倧ãããªããšãããã¯ãã¯ã䟿å©ã§ã¯ãªããããããŸããããæåã¯éåžžã«é©ããŠããŸãã
Springã®äž»ãªæ§æã¯ã次ã®è¡ã§å®çŸ©ãããŸãã
@SpringBootTest
ã¢ããªã±ãŒã·ã§ã³ã®ã³ã³ããã¹ããèšå®ããããã«äœ¿çšãããŸãã
WebEnvironment.NONE
ã¯ãWebã³ã³ããã¹ããäžããå¿ èŠããªãããšãæå³ããŸãã
@Transactional
Transactional-ãã©ã³ã¶ã¯ã·ã§ã³å ã®ãã¹ãŠã®ã¯ã©ã¹ãã¹ããèªåããŒã«ããã¯ã§ã©ããããŠãããŒã¿ããŒã¹ã®ç¶æ ãä¿åããŸãã
è©Šéšæ§é
ProductController
ã¯ã©ã¹ã®ãã¹ãã®æå°éã®ã»ããã§ãã
ProductController
ãŸãããã
@Test public void createProduct_productSaved() { Product product = product("productName").price("1.01").discount("0.1").advertised(true).build(); Product createdProduct = productController.createProduct(product); Product dbProduct = productRepository.getOne(createdProduct.getId()); assertEquals("productName", dbProduct.getName()); assertEquals(number("1.01"), dbProduct.getPrice()); assertEquals(number("0.1"), dbProduct.getDiscount()); assertEquals(true, dbProduct.isAdvertised()); }
ãã¹ãã³ãŒãã¯éåžžã«ã·ã³ãã«ã§ãäžç®ã§ç解ã§ãããã®ã§ãªããã°ãªããŸããã ããã§ãªãå Žåãèšäºã®æåã®ã»ã¯ã·ã§ã³ã§èª¬æãããã¹ãã®å©ç¹ã®ã»ãšãã©ã倱ãããŸãã ãã¹ãæ¬äœããèŠèŠçã«äºãã«åé¢ã§ãã3ã€ã®éšåã«åå²ããããšããå§ãããŸããããŒã¿ã®æºåããã¹ãã¡ãœããã®åŒã³åºããçµæã®æ€èšŒã§ãã åæã«ããã¹ãã³ãŒããç»é¢å šäœã«åãŸãããšãéåžžã«æãŸããã§ãã
å人çã«ã¯ãããŒã¿æºåã»ã¯ã·ã§ã³ã®ãã¹ãå€ãåŸã®ãã§ãã¯ã§äœ¿çšããããšãããæçœã«æããŸãã ãŸãã¯ã次ã®ããã«ãªããžã§ã¯ããæ瀺çã«æ¯èŒããããšãã§ããŸãã
assertEquals(product, dbProduct);
補åæ å ±ãæŽæ°ããå¥ã®ãã¹ãïŒ
updateProduct
ïŒã§ã¯ãããŒã¿ã®äœæãããå°ãè€éã«ãªãããã¹ãã®3ã€ã®éšåã®èŠèŠçæŽåæ§ãç¶æããããã«ã2ã€ã®è¡ãã£ãŒããé£ç¶ããŠåé¢ãããŠããããšãæããã§ãïŒ
@Test public void updateProduct_productUpdated() { Product product = product("productName").build(); productRepository.save(product); Product updatedProduct = product("updatedName").price("1.1").discount("0.5").advertised(true).build(); updatedProduct.setId(product.getId()); productController.updateProduct(product.getId(), updatedProduct); Product dbProduct = productRepository.getOne(product.getId()); assertEquals("updatedName", dbProduct.getName()); assertEquals(number("1.1"), dbProduct.getPrice()); assertEquals(number("0.5"), dbProduct.getDiscount()); assertEquals(true, dbProduct.isAdvertised()); }
çå°ã®3ã€ã®éšåã¯ããããåçŽåã§ããŸãã ããŒã¿ã®æºåã«ã¯ããã¹ããã«ããŒãåªããŠããŸããããã«ã¯ããã¹ããã䜿çšããã®ã«äŸ¿å©ãªãªããžã§ã¯ããäœæããããã®ããžãã¯ãå«ãŸããŠããŸãã ããŸãã«ãè€éãªã¡ãœããåŒã³åºãããã¹ãã¯ã©ã¹å ã®è£å©ã¡ãœããã«ããŠããã®ã¯ã©ã¹ã«é¢ä¿ã®ãªããã©ã¡ãŒã¿ãŒã®äžéšãé衚瀺ã«ããããšãã§ããŸãã è€éãªãã§ãã¯ãç°¡çŽ åããããã«ãè£å©é¢æ°ãäœæããããç¬èªã®ãããã£ãŒãå®è£ ããããšãã§ããŸãã ããããã¹ãŠã®åçŽåã®äž»ãªããšã¯ããã¹ãã®å¯èŠæ§ã倱ãããšã§ã¯ãããŸããããã¹ãŠãã¡ã€ã³ã¡ãœããã§äžç®ã§ãããããã«ããããã«æ·±ãããå¿ èŠã¯ãããŸããã
ãã¹ããã«ããŒ
ãã¹ããã«ããŒã«ã¯ç¹å¥ãªæ³šæãå¿ èŠã§ãã ãªããžã§ã¯ãäœæã®ããžãã¯ãã«ãã»ã«åãããšããã¹ãã®ã¡ã³ããã³ã¹ãç°¡åã«ãªããŸãã ç¹ã«ããã®ãã¹ãã«é¢ä¿ã®ãªãã¢ãã«ãã£ãŒã«ãã®å ¥åã¯ããã«ããŒå ã§é衚瀺ã«ã§ããŸãã ãããè¡ãã«ã¯ãçŽæ¥äœæããå¿ èŠã¯ãããŸããããæ¬ èœããŠãããã£ãŒã«ãã«ããã©ã«ãå€ãå ¥åããéçã¡ãœããã䜿çšããŸãã ããšãã°ãæ°ããå¿ é ãã£ãŒã«ããã¢ãã«ã«è¡šç€ºãããå Žåããã®ã¡ãœããã«ç°¡åã«è¿œå ã§ããŸãã
ProductBuilder
ã次ã®ããã«ãªããŸãã
public static ProductBuilder product(String name) { return new ProductBuilder() .name(name) .advertised(false) .price("0.00"); }
ãã¹ãå
ãã®ãã¹ãã§å ·äœçã«äœããã¹ããããããç解ããããšãäžå¯æ¬ ã§ãã æ確ã«ããããã«ãã¿ã€ãã«ã§ãã®è³ªåã«çããã®ãæåã§ãã
getProduct
ã¡ãœããã®ãµã³ãã«ãã¹ãã䜿çšããŠã䜿çšãããåœåèŠåãæ€èšããŠãã ããã
@Test public void getProduct_oneProductInDb_productReturned() { Product product = product("productName").build(); productRepository.save(product); Product result = productController.getProduct(product.getId()); assertEquals("productName", result.getName()); } @Test public void getProduct_twoProductsInDb_correctProductReturned() { Product product1 = product("product1").build(); Product product2 = product("product2").build(); productRepository.save(product1); productRepository.save(product2); Product result = productController.getProduct(product1.getId()); assertEquals("product1", result.getName()); }
äžè¬çãªå Žåããã¹ãã¡ãœããã®èŠåºãã¯ãäžç·ã§åºåããã3ã€ã®éšåã§æ§æãããŸãããã¹ãããã¡ãœããã®ååãã¹ã¯ãªãããããã³æåŸ ãããçµæã§ãã ãã ãã誰ãåžžèãåãæ¶ããŸããã§ããããã®ã³ã³ããã¹ãã§å¿ èŠã§ãªãå Žåã¯ãååã®äžéšãçç¥ããããšã¯æ£åœåãããå ŽåããããŸãïŒããšãã°ã補åãäœæããããã®åäžãã¹ãã®ã¹ã¯ãªããïŒã ãã®åœåã®ç®çã¯ãã³ãŒããåŠç¿ããã«åãã¹ãã®æ¬è³ªãç解ã§ããããã«ããããšã§ãã ããã«ããããã¹ãçµæã®ãŠã£ã³ããŠãã§ããéãæ確ã«ãªããéåžžã¯ãã¹ãã®äœæ¥ãéå§ãããŸãã
çµè«
以äžã§ãã
ProductController
ã¯ã©ã¹ã®ã¡ãœããããã¹ãããã«ã¯ãåããŠ4ã€ã®ãã¹ãã®æå°éã®ã»ããã§ååã§ãã ãã°ãæ€åºããå Žåããã€ã§ãæ¬ èœããŠãããã¹ããè¿œå ã§ããŸãã åæã«ããã¹ãã®æå°æ°ã¯ããããããµããŒãããæéãšåŽåãå€§å¹ ã«åæžããŸãã æåã®ãã¹ãã¯éåžžââæé«ã®å質ã§ã¯ãªããå€ãã®äºæããªãåé¡ãåŒãèµ·ãããããããã¯ãã¹ãã®å®è£ ã«ãããŠéèŠã§ãã åæã«ããã®ãããªãã¹ãã¹ã€ãŒãã¯ãèšäºã®æåã®éšåã§èª¬æããããŒãã¹ãåãåãã®ã«ååã§ãã
ãã®ãããªãã¹ãã¯ã¢ããªã±ãŒã·ã§ã³ã®Webã¬ã€ã€ãŒããã§ãã¯ããŸããããå€ãã®å Žåããã¯å¿ é ã§ã¯ãããŸããã å¿ èŠã«å¿ããŠãããŒã¹ïŒ
@WebMvcTest
ã
MockMvc
ã
@MockBean
ïŒã®ä»£ããã«ã¹ã¿ãã䜿çšããŠWebã¬ã€ã€ãŒã®åå¥ã®ãã¹ããäœæããããæ¬æ ŒçãªãµãŒããŒã䜿çšã§ããŸãã ãã¹ãã§ã¯ãµãŒããŒã®ãã©ã³ã¶ã¯ã·ã§ã³ãå¶åŸ¡ã§ããªããããåŸè ã¯ãããã°ãè€éã«ãããã©ã³ã¶ã¯ã·ã§ã³ã®åŠçãè€éã«ããå¯èœæ§ããããŸãã ãã®ãããªçµ±åãã¹ãã®äŸã¯ã
CustomerControllerServerIT
ã¯ã©ã¹ã«ãããŸãã
åäœãã¹ã
åäœãã¹ãã«ã¯ãçµ±åãã¹ããããããã€ãã®å©ç¹ããããŸãã
- èµ·åã«ã¯æ°ããªç§ããããŸãã
- ãã¹ãæžã¿ãŠãããã®ãµã€ãºãå°ããã
- ã¡ãœãããçŽæ¥åŒã³åºããšãããŒã¿ã®æºåãå€§å¹ ã«ç°¡çŽ åããããããå€æ°ã®ãªãã·ã§ã³ã®æ€èšŒãç°¡åã«å®è£ ã§ããŸãã
ããã«ãããããããåäœãã¹ãã¯ãã®æ§è³ªäžãã¢ããªã±ãŒã·ã§ã³å šäœã®æäœæ§ãä¿èšŒããããšã¯ã§ãããçµ±åãã¹ãã®äœæãé¿ããããšã¯ã§ããŸããã ãã¹ã察象ã®ãŠãããã®ããžãã¯ãåçŽãªå ŽåããŠããããã¹ããšçµ±åãã¹ããè€è£œããŠãã¡ãªããã¯ãããŸãããããµããŒãããã³ãŒããè¿œå ããã ãã§ãã
ãã®äŸã§åäœãã¹ãã«å€ããå¯äžã®ã¯ã©ã¹ã¯
BonusPointCalculator
ã§ãã ãã®éç«ã£ãæ©èœã¯ãããžãã¹ããžãã¯ã®å€æ°ã®ãã©ã³ãã§ãã ããšãã°ããã€ã€ãŒã補åã®ã³ã¹ãã®10ïŒ ã®ããŒãã¹ãåãåãã次ã®ãªã¹ããã2ã€ä»¥äžã®ä¹æ°ãä¹ç®ããããšä»®å®ããŸãã
- 補åã®äŸ¡æ Œã¯10,000ïŒÃ4ïŒä»¥äžã§ãã
- 補åã¯åºåãã£ã³ããŒã³ã«åå ããŠããŸãïŒÃ3ïŒã
- 補åã¯ã顧客ã®ããæ°ã«å ¥ãã補åã§ãïŒÃ5ïŒã
- ã¯ã©ã€ã¢ã³ãã«ã¯ãã¬ãã¢ã ã¹ããŒã¿ã¹ïŒÃ2ïŒããããŸãã
- ã¯ã©ã€ã¢ã³ãã«ãã¬ãã¢ã ã¹ããŒã¿ã¹ããããããæ°ã«å ¥ããã®è£œåãè³Œå ¥ããå Žåã瀺ãããŠãã2ã€ã®ä¹æ°ã®ä»£ããã«1ã€ïŒÃ8ïŒã䜿çšãããŸãã
ãã¡ãããå®éã«ã¯ããããã®ããŒãã¹ãèšç®ããããã®æè»ãªæ±çšã¡ã«ããºã ãèšèšãã䟡å€ããããŸãããäŸãåçŽåããããã«ãåºå®ãããå®è£ ã«éå®ããŠããŸãã ä¹æ°ã®èšç®ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
private List<BigDecimal> calculateMultipliers(Customer customer, Product product) { List<BigDecimal> multipliers = new ArrayList<>(); if (customer.getFavProduct() != null && customer.getFavProduct().equals(product)) { if (customer.isPremium()) { multipliers.add(PREMIUM_FAVORITE_MULTIPLIER); } else { multipliers.add(FAVORITE_MULTIPLIER); } } else if (customer.isPremium()) { multipliers.add(PREMIUM_MULTIPLIER); } if (product.isAdvertised()) { multipliers.add(ADVERTISED_MULTIPLIER); } if (product.getPrice().compareTo(EXPENSIVE_THRESHOLD) >= 0) { multipliers.add(EXPENSIVE_MULTIPLIER); } return multipliers; }
å€æ°ã®ãªãã·ã§ã³ããããããããã§ã¯2ã€ãŸãã¯3ã€ã®çµ±åãã¹ããå¶éãããŸããã åäœãã¹ãã®æå°éã®ã»ããã¯ããã®ãããªæ©èœã®ãããã°ã«æé©ã§ãã
察å¿ãããã¹ãã¹ã€ãŒãã¯
BonusPointCalculatorTest
ã¯ã©ã¹ã«ãããŸãã ãããã®ããã€ãã次ã«ç€ºããŸãã
@Test public void calculate_oneProduct() { Product product = product("product").price("1.00").build(); Customer customer = customer("customer").build(); Map<Product, Long> quantities = mapOf(product, 1L); BigDecimal bonus = bonusPointCalculator.calculate(customer, list(product), quantities::get); BigDecimal expectedBonus = bonusPoints("0.10").build(); assertEquals(expectedBonus, bonus); } @Test public void calculate_favProduct() { Product product = product("product").price("1.00").build(); Customer customer = customer("customer").favProduct(product).build(); Map<Product, Long> quantities = mapOf(product, 1L); BigDecimal bonus = bonusPointCalculator.calculate(customer, list(product), quantities::get); BigDecimal expectedBonus = bonusPoints("0.10").addMultiplier(FAVORITE_MULTIPLIER).build(); assertEquals(expectedBonus, bonus); }
ãã¹ãã§ã¯ããããªãã¯ã¯ã©ã¹API-
calculate
ã¡ãœãããå ·äœçã«åç §ããŠããããšã«æ³šæããŠãã ããã å®è£ ã§ã¯ãªãã¯ã©ã¹ã³ã³ãã©ã¯ãããã¹ããããšãæ©èœä»¥å€ã®å€æŽããªãã¡ã¯ã¿ãªã³ã°ã«ãããã¹ãã®æ éãåé¿ã§ããŸãã
æåŸã«ãåäœãã¹ãã§å éšããžãã¯ããã¹ããããšãã«ãããããã¹ãŠã®è©³çŽ°ãçµ±åããå¿ èŠããªããªããŸããã ãã®å Žåã1ã€ã®å€ããå°ãªãã代衚çãªãã¹ãã§ååã§ããããšãã°ã次ã®ãšããã§ãã
@Test public void calculateBonusPoints_twoProductTypes_correctValueCalculated() { Product product1 = product("product1").price("1.01").build(); Product product2 = product("product2").price("10.00").build(); productRepository.save(product1); productRepository.save(product2); Customer customer = customer("customer").build(); customerRepository.save(customer); Map<Long, Long> quantities = mapOf(product1.getId(), 1L, product2.getId(), 2L); BigDecimal bonus = customerController.calculateBonusPoints( new CalculateBonusPointsRequest("customer", quantities) ); BigDecimal bonusPointsProduct1 = bonusPoints("0.10").build(); BigDecimal bonusPointsProduct2 = bonusPoints("1.00").quantity(2).build(); BigDecimal expectedBonus = bonusPointsProduct1.add(bonusPointsProduct2); assertEquals(expectedBonus, bonus); }
çµ±åãã¹ãã®å Žåãšåæ§ã«ã䜿çšãããåäœãã¹ãã®ã»ããã¯éåžžã«å°ãããã¢ããªã±ãŒã·ã§ã³ã®å®å šæ§ãä¿èšŒãããã®ã§ã¯ãããŸããã ããã§ãããã®ååšã¯ã³ãŒãã®ä¿¡é Œæ§ãå€§å¹ ã«é«ãããããã°ã容æã«ããèšäºã®æåã®éšåã«ãªã¹ããããŠããä»ã®ããŒãã¹ãäžããŸãã
å®è£ ã®æšå¥šäºé
åã®ã»ã¯ã·ã§ã³ã§ãå°ãªããšã1人ã®éçºè ãããââãžã§ã¯ãã§ãã¹ãã®äœ¿çšãéå§ããããã«èª¬åŸããã®ã«ååã§ããããšãé¡ã£ãŠããŸãã ãã®ç« ã§ã¯ãæ·±å»ãªåé¡ãåé¿ããåæå®è£ ã³ã¹ããåæžããã®ã«åœ¹ç«ã€äž»ãªæšå¥šäºé ãç°¡åã«ãªã¹ãããŸãã
æ°ããã¢ããªã±ãŒã·ã§ã³ã§ãã¹ãã®å®è£ ãéå§ããŠã¿ãŠãã ããã 倧èŠæš¡ãªã¬ã¬ã·ãŒãããžã§ã¯ãã§æåã®ãã¹ããæžãããšã¯ãæ°ããäœæãããããžã§ã¯ããããã¯ããã«é£ãããããå€ãã®ã¹ãã«ãå¿ èŠãšããŸãã ãããã£ãŠãå¯èœã§ããã°ãå°ããªæ°ããã¢ããªã±ãŒã·ã§ã³ããéå§ããããšããå§ãããŸãã æ°ããæ¬æ Œçãªã¢ããªã±ãŒã·ã§ã³ãæåŸ ãããŠããªãå Žåã¯ãå éšã§äœ¿çšããããã®æçšãªãŠãŒãã£ãªãã£ã®éçºãè©Šã¿ãããšãã§ããŸãã äž»ãªããšã¯ãã¿ã¹ã¯ãå€ããå°ãªããçŸå®çã§ããã¹ãã ãšããããšã§ã-çºæãããäŸã¯æ¬æ ŒçãªçµéšãäžããŸããã
å®æçãªãã¹ãå®è¡ãèšå®ããŸãã ãã¹ããå®æçã«å®è¡ãããªãå Žåãã¡ã€ã³æ©èœã®å®è¡ãåæ¢ããã ãã§ãªããã³ãŒãã®æ£ç¢ºæ§ã確èªããã ãã§ãªããããã«å€ããªã£ãŠããŸããŸãã ãããã£ãŠããªããžããªã§ã³ãŒããæŽæ°ããããã³ã«ãã¹ããèªåçã«èµ·åããããã«ãå°ãªããšãæå°éã®CIãã€ãã©ã€ã³ãæ§æããããšãéåžžã«éèŠã§ãã
ã«ããŒãè¿œããããªãã§ãã ããã ä»ã®æè¡ã®å Žåã®ããã«ãæåã¯æé«å質ã®ãã¹ãã¯ååŸãããŸããã é¢é£ããæç®ïŒèšäºã®æåŸã«ãããªã³ã¯ïŒãŸãã¯æèœãªã¡ã³ã¿ãŒãããã§åœ¹ç«ã¡ãŸãããããã¯èªå·±å å¡«ã³ãŒã³ã®å¿ èŠæ§ããã£ã³ã»ã«ããŸããã ãã®ç¹ã§ã®ãã¹ãã¯ãã³ãŒãã®æ®ãã®éšåãšäŒŒãŠããŸãããããžã§ã¯ãã«ã©ã®ããã«åœ±é¿ããããç解ããããã«ã¯ããã°ãããã¹ããè¡ã£ãŠããã§ãªããã°ã§ããŸããã ãããã£ãŠã被害ãæå°éã«æããããã«ãæåã¯100ïŒ ã®ã«ãã¬ããžã®ãããªæ°åãçŸããæ°åãè¿œããããªãæ¹ãè¯ãã§ãããã 代ããã«ãç¬èªã®ã¢ããªã±ãŒã·ã§ã³æ©èœã®äž»ãªè¯å®çãªã·ããªãªã«éå®ããå¿ èŠããããŸãã
åäœãã¹ãã«å€¢äžã«ãªããªãã§ãã ããã ãé察å質ããšããããŒããç¶ãããšãæ£çŽãªåäœãã¹ãã¯åããŠå®è¡ãããã¹ãã§ã¯ãªãããšã«æ³šæããå¿ èŠããããŸããããã¯ãã¢ããªã±ãŒã·ã§ã³ã®éå°ãªä»æ§ã«å®¹æã«ã€ãªããå¯èœæ§ãããããã§ãã 次ã«ãããã¯ãåŸç¶ã®ãªãã¡ã¯ã¿ãªã³ã°ããã³ã¢ããªã±ãŒã·ã§ã³ã®æ¹åäžã«é倧ãªé»å®³èŠå ã«ãªããŸãã åäœãã¹ãã¯ãç¹å®ã®ã¯ã©ã¹ãŸãã¯ã¯ã©ã¹ã®ã°ã«ãŒãã«è€éãªããžãã¯ãããå Žåã«ã®ã¿äœ¿çšããå¿ èŠããããŸããããã¯ãçµ±åã¬ãã«ã§ç¢ºèªããã«ã¯äžäŸ¿ã§ãã
ã¹ã¿ãã¯ã©ã¹ãšã¢ããªã±ãŒã·ã§ã³ã¡ãœããã«å€¢äžã«ãªããªãã§ãã ããã ã¹ã¿ãïŒã¹ã¿ããã¢ãã¯ïŒã¯ããã©ã³ã¹ã®åããã¢ãããŒããšãã©ã³ã¹ã®ç¶æãå¿ èŠãšãããã1ã€ã®ããŒã«ã§ãã äžæ¹ã§ã¯ããŠããããå®å šã«åé¢ããããšã§ãã·ã¹ãã ã®æ®ãã®éšåã«ã€ããŠèããããšãªãããã¹ãæžã¿ã®ããžãã¯ã«éäžããããšãã§ããŸãã äžæ¹ãããã«ã¯è¿œå ã®éçºæéãå¿ èŠã§ãããåäœãã¹ããšåæ§ã«ãåäœã®éå°ãªæå®ã«ã€ãªããå¯èœæ§ããããŸãã
å€éšã·ã¹ãã ããçµ±åãã¹ãã解ããŸãã çµ±åãã¹ãã§ããããééãã¯ãå®éã®ããŒã¿ããŒã¹ãã¡ãã»ãŒãžãã¥ãŒãããã³ã¢ããªã±ãŒã·ã§ã³å€éšã®ä»ã®ã·ã¹ãã ã®äœ¿çšã§ãã ãã¡ãããå®éã®ç°å¢ã§ãã¹ããå®è¡ããæ©èœã¯ããããã°ãšéçºã«åœ¹ç«ã¡ãŸãã ãã®ãããªå°éã®ãã¹ãã¯ãç¹ã«ã€ã³ã¿ã©ã¯ãã£ãã«å®è¡ããå Žåã«æå³ããããŸãã ãã ãããããã®åºç¯ãªäœ¿çšã¯å€ãã®åé¡ã«ã€ãªãããŸãã
- ãã¹ããå®è¡ããã«ã¯ãå€éšç°å¢ãæ§æããå¿ èŠããããŸãã ããšãã°ãã¢ããªã±ãŒã·ã§ã³ãã¢ã»ã³ãã«ãããåãã·ã³ã«ããŒã¿ããŒã¹ãã€ã³ã¹ããŒã«ããŸãã ããã«ãããæ°ããéçºè ãããââãžã§ã¯ãã«åå ããŠCIãæ§æããããšãé£ãããªããŸãã
- å€éšã·ã¹ãã ã®ç¶æ ã¯ããã¹ããå®è¡ããåã«ãã·ã³ã«ãã£ãŠç°ãªãå ŽåããããŸãã ããšãã°ãããŒã¿ããŒã¹ã«ã¯ããã¹ãã§äºæãããŠããªãããŒã¿ã§ã¢ããªã±ãŒã·ã§ã³ãå¿ èŠãšããããŒãã«ãæ¢ã«å«ãŸããŠããå ŽåããããŸãã ããã«ããããã¹ãã§äºæž¬äžå¯èœãªé害ãçºçãããããã®é€å»ã«ã¯ããªãã®æéãããããŸãã
- è€æ°ã®ãããžã§ã¯ãã§äžŠè¡äœæ¥ãé²è¡ããŠããå Žåãäžéšã®ãããžã§ã¯ããä»ã®ãããžã§ã¯ãã«éèªæãªåœ±é¿ãäžããå¯èœæ§ããããŸãã ããšãã°ããããžã§ã¯ãã®1ã€ã«å¯ŸããŠè¡ãããç¹å®ã®ããŒã¿ããŒã¹èšå®ã¯ãå¥ã®ãããžã§ã¯ãã®æ©èœãæ£ããæ©èœããã®ã«åœ¹ç«ã¡ãŸãããå¥ã®ãã·ã³ã®ã¯ãªãŒã³ããŒã¿ããŒã¹ã§èµ·åãããšå£ããŸãã
- ãã¹ãã¯é·æéå®è¡ãããŸãããã«å®è¡ã«ã¯æ°ååãããå ŽåããããŸãã ããã¯ãéçºè ããã¹ããããŒã«ã«ã§å®è¡ããã®ãåæ¢ãããªã¢ãŒããªããžããªã«å€æŽãéä¿¡ããåŸã«ã®ã¿çµæã確èªãããšããäºå®ã«ã€ãªãããŸãã ãã®åäœã¯ããã®èšäºã®æåã®éšåã§èª¬æãããã¹ãã®å©ç¹ã®ã»ãšãã©ãç¡å¹ã«ããŸãã
çµ±åãã¹ãéã®ã³ã³ããã¹ããã¯ãªã¢ããŸãã å€ãã®å Žåãçµ±åãã¹ããé«éåããã«ã¯ããããã®éã§åãã³ã³ããã¹ããåå©çšããå¿ èŠããããŸãã Springã®å ¬åŒããã¥ã¡ã³ãã§ããã®ãããªæšå¥šäºé ããããŸãã åæã«ãçžäºã®ãã¹ãã®åœ±é¿ãé¿ããå¿ èŠããããŸãã ãããã¯ä»»æã®é åºã§èµ·åãããããããã®ãããªæ¥ç¶ãååšãããšãã©ã³ãã ã§åçŸäžå¯èœãªãšã©ãŒãçºçããå¯èœæ§ããããŸãã ãããé²ãããã«ããã¹ãã§ã¯ã³ã³ããã¹ãã®å€æŽãæ®ããªãã§ãã ããã ããšãã°ãããŒã¿ããŒã¹ã䜿çšããå Žåãéåžžã¯åé¢ã®ããã«ããã¹ãã§ã³ãããããããã¹ãŠã®ãã©ã³ã¶ã¯ã·ã§ã³ãããŒã«ããã¯ããã ãã§ååã§ãã ã³ã³ããã¹ãã®å€æŽãé¿ããããªãå Žåã¯ã
@DirtiesContext
ã¢ãããŒã·ã§ã³ã䜿çšããŠãã®ã¬ã¯ãªãšãŒã·ã§ã³ãèšå®ã§ããŸãã
ãã¹ãã劥åœãªæéå ã«å®è¡ãããããšã確èªããŠãã ããããã¹ããå®éã®å€éšã·ã¹ãã ã«äŸåããŠããªããŠããå®è¡æéã¯ç°¡åã«æã«è² ããªããªãå¯èœæ§ããããŸãããããé²ãã«ã¯ããã®ã€ã³ãžã±ãŒã¿ãåžžã«ç£èŠããå¿ èŠã«å¿ããŠå¯Ÿçãè¬ããå¿ èŠããããŸããå®è¡ã§ããæå°ã®æ¹æ³ã¯ãäœéãã¹ããåå¥ã®ã°ã«ãŒãã«åããŠããããã«é¢ä¿ã®ãªãã¿ã¹ã¯ã®äœæ¥ã劚ããªãããã«ããããšã§ãã
ãã¹ããã§ããã ãæ確ã§èªã¿ããããã®ã«ããŠãã ãããäŸã§ãã§ã«ç€ºããããã«ããã¹ãã¯ç解ããå¿ èŠããªãããã«äœæããå¿ èŠããããŸãããã¹ãã®åŠç¿ã«è²»ãããæéã¯ãã³ãŒãã®åŠç¿ã«è²»ããããšãã§ããŸãã
TDDïŒãã¹ãé§åéçºïŒã§ãã³ã°ã¢ããããªãã§ãã ãããTDDã¯ããªãäžè¬çãªæ¹æ³ã§ãããç¹ã«å®è£ ã®åæ段éã§ã¯ãTDDã¯å¿ é ã§ã¯ãããŸãããäžè¬ã«ãé©åãªãã¹ããäœæããèœåã¯ããã¹ããäœæããæç¹ãšã¯é¢ä¿ãããŸãããããã¯æéãç¯çŽããããã®äž»èŠãªæ¹æ³ã®1ã€ã§ãããããæ¬åœã«éèŠãªã®ã¯ããã¹ãã§æ¢ã«ã³ãŒãã®åæãããã°ãè¡ãããšã§ãã
æåã®ãã¹ãã¯æžãããŠããŸããã次ã¯äœã§ããïŒ
次ã«ããããžã§ã¯ãã®ãã¹ãã®å¯¿åœã泚ææ·±ãç£èŠãã次ã®ãããªè³ªåãå®æçã«èªåããå¿ èŠããããŸãã
- ã©ã®ãã¹ãããªãã¡ã¯ã¿ãªã³ã°ãšæ¹åã劚ããŸããïŒäžå®ã®ä¿®æ£ãå¿ èŠã§ãïŒïŒãã®ãããªãã¹ãã¯ãæžãçŽããããããžã§ã¯ãããå®å šã«åé€ããŠãããé«ããã¹ãã«çœ®ãæããå¿ èŠããããŸãã
- ç°ãªãç°å¢ïŒååã®ã³ã³ãã¥ãŒã¿ãŒãCIãµãŒããŒïŒã§å®è¡ããŠããå Žåãè€æ°ã®èµ·åãŸãã¯äžŠåèµ·åäžã«é »ç¹ã«ãäºæž¬ã§ããªããã¹ããè¡ââãããŸããïŒãŸããåŠçãå¿ èŠã§ãã
- ã©ã®ãšã©ãŒããã¹ãã«åæ ŒããŸããïŒãã®ãããªãã°ããšã«ãæ°ãããã¹ããè¿œå ããåæ§ã®æ©èœã®ãã¹ããäœæãããšãã«ããããå°æ¥çã«èæ ®ããŠããããšããå§ãããŸãã
- ã©ã®ãã¹ããé·ãããŸããïŒããããæžãçŽããªããã°ãªããŸããããããäžå¯èœãªå Žåã¯ãããŒã«ã«ã§å®è¡ãããå¯èœæ§ãç¶æããããã«ãããããããé«éãªãã®ããåé¢ããŸãã
ããã«ããã®èšäºã®åé ã§èª¬æãããã¹ãã®å©ç¹ã«æ³šæãã䟡å€ããããŸããããªããããããåãåããªãã£ãå Žåãäœããééã£ãŠããŸããå®æçãªå顧ã¯ã䜿çšãããã¹ãã®å質ãšæå¹æ§ãäžè²«ããŠåäžãããæãå®äŸ¡ãªæ¹æ³ã§ãã
ãããã«
æåã¯ããã¹ãã®æ°ãè¿œããããã®ã§ã¯ãªãããã¹ãã®å質ã«çŠç¹ãåœãŠãæ¹ãè¯ãã§ããèšå€§ãªæ°ã®äžé©åãªåäœãã¹ãã¯ãç°¡åã«ã¢ã³ã«ãŒã«ãªãããããžã§ã¯ããåºèŸºã«åŒã蟌ãå¯èœæ§ããããŸããããã«ãåäœãã¹ãã®ååšã¯ãçµ±åãã¹ããèšè¿°ããå¿ èŠæ§ãå ããŸããããããã£ãŠãæåã®æãå¹æçãªæŠç¥ã¯ãçµ±åãã¹ãã§äž»ãªããžãã£ãã·ããªãªãã«ããŒããããšããå§ããããã§ååã§ãªãå Žåã¯ããŠããããã¹ãã§ããŒã«ã«ãã§ãã¯ãè¿œå ããããšã§ããæéãçµã€ã«ã€ããŠãã£ãŒãããã¯ãèç©ãããããã«ããããã¹ãä¿®æ£ããããŸããŸãªèªåãã¹ãæ¹æ³ã®å¹æçãªäœ¿çšã«ã€ããŠããæ確ãªã¢ã€ãã¢ãåŸãããšãã§ããŸãã
èªãã§ãã人ãã¡ã®äžã«ãç§ã®éã®çŽ°ã匊ãç§ã®æžçã®åœ±é¿ãåãã人ãã¡ãããããšãé¡ã£ãŠããŸãããããŠãããã«å¹æçã§å¹æçãªãã¹ããå«ãããã€ãã®ãããžã§ã¯ããäžçã«çŸããã§ãããïŒ
GitHubãããžã§ã¯ãã®ãœãŒã¹
æçšãªæç®
Growing Object-Oriented Software, Guided by Tests , Steve Freeman, Nat Pryce
The Art of Unit Testing , Roy Osherove
Test-driven Development: By Example , Kent Beck
Refactoring: Improving the Design of Existing Code , Martin Fowler
The Art of Unit Testing , Roy Osherove
Test-driven Development: By Example , Kent Beck
Refactoring: Improving the Design of Existing Code , Martin Fowler