åãã«
kintoneãã¼ã ã®åç°ã§ãã kintoneã¯ãªãªã¼ã¹ãã10年以ä¸çµéãSeleniumãã¹ãã®æ°ãè¨å¤§ã«ãªã£ã¦ãããéçºããã»ã¹ã«éãã®ãããã£ã¦ãã¦ãã¾ãã ããã§ãæ¬ç©ã®DBããæ¬ç©ã®ãµã¼ãã¹ã¨åçã®æ¯ãèãããããã§ã¤ã¯ã使ã£ãæ°ãããã¹ããæè¿è©¦ãã¦ãã¾ãã ãã®ãã¹ãã¯kintoneã®ãµã¼ãã¼ãèµ·åããªããã軽éã«å®è¡ã§ããªãããã Seleniumãã¹ãã¨åçã®ä¿è·ãåãã¦ãããããªæè§¦ãæ´ããããã«ãªã£ã¦ãã¾ãã æ¬è¨äºã§ã¯ãã®æ°ãããã¹ãã«ã¤ãã¦ç´¹ä»ãã¾ãã
ãã¹ãã®æ¸ãæ¹
æ¬ç©ã®DBããã§ã¤ã¯ã使ã£ããã¹ãã¯ä¸ã®ãããªå§¿ã«ãªã£ã¦ãã¾ãã ä»åç´¹ä»ãããã¹ãã¯ãã®ãããªJavaã®ã¯ã©ã¹ã®ãã¹ãã§ãã ã¡ãªã¿ã«ãã¹ããã¬ã¼ã ã¯ã¼ã¯ã¯JUnitã§ãã
class RecordServiceTest { @Inject private FakeUserService fakeUserService; @Inject private AppService appService; @Inject private RecordService recordService @Test public void testAddRecord() { // Setup: ã¢ããªãæºå // userã追å User user = fakeUserService.registerUser("user"); // ã¢ããªãã¯ãããã使 App app = appService.add("App") // ã¢ããªã«ãã£ã¼ã«ãã追å appService.addFields(app, List.of(SingleLineTextField.of("æåå__1è¡_"))); // ã¢ããªãããã㤠appService.deploy(app); // Exercise: ã¬ã³ã¼ãã追å long recordId = recordService.addRecord(app, user.getId(), List.of(Field.singleLineText("æåå__1è¡_", "ãããã¤"))); // Verify: 追å ããã¬ã³ã¼ããåå¾ã§ããããç¢ºèª List<Record> records = recordService.listByIds(app, user.getId(), List.of(recordId)); assertThat(records.get(0).getValue("æåå__1è¡_").orElseThrow()).isEqualTo("ãããã¤"); } }
ããã§ã¯RecordServiceã¨ããã¯ã©ã¹ã®addRecordã¨ããã¡ã½ããã®ãã¹ããä¾ã«ãã¦ãã¾ãã
RecordSerivceã¯kintoneã®ã¢ããªã®ã¬ã³ã¼ãã«é¢ããå¦çãæ
å½ããã¯ã©ã¹ã§ã
addRecordã¯ã¢ããªã¨ãã¼ã¿ã弿°ã«ã¨ã£ã¦ã¢ããªã®ã¬ã³ã¼ãã¨ãã¦ãã¼ã¿ãDBã«ä¿åãã¾ãã
addRecordã®ãã¹ãã§ã¯ãã¹ãç¨ã®ãã¼ã¿ã使ã£ã¦ä¿åã試ã¿ããã®å¾ã«ãã¼ã¿ãåå¾ãã¦ä¿åæã®ãã®ã¨ä¸è´ãããã確èªãã¦ãã¾ãã
æ¬ç©ã®DBã使ãã¨æåã«è¿°ã¹ãéãããã¼ã¿ã®ä¿åã§ã¯å®éã«æ¬ç©ã®DBã«ä¿åãã¦ãã¾ãã ãã¼ã¿ã®åå¾ã§ã¯åãDBããåå¾ãã¦ãã¾ãã ãã¹ããå®è¡ããæã¯MySQLãèµ·åãããã¹ãã³ã¼ãããã¢ã¯ã»ã¹ããã¦ãã¾ãã ãã®ä»ã«ãSetupã§ã¢ããªãã¯ãããã使ããã£ã¼ã«ãã追å ããç®æã§ã使ããã¢ããªã¯DBã«ä¿åããã¦ãã¾ãã
æ¬ç©ã®DB以å¤ã«ããFakeUserServiceã¨ããUserServiceã®ãã§ã¤ã¯ã使ã£ã¦ãã¾ãã
ã¾ãUserServiceã®èª¬æãããã¨ãã¦ã¼ã¶ã¼ã®è¿½å ãã¦ã¼ã¶ã¼ä¸è¦§ã®åå¾ãªã©ã®ã¦ã¼ã¶ã¼ã«é¢ãããµã¼ãã¹ãå¥ãµã¼ãã¹ã¨ãã¦kintoneã¨ã¯å¥ã®ãµã¼ãã¼ã§ç¨¼åãã¦ãã¾ãã
ãã®ãµã¼ãã¹ã«ã¢ã¯ã»ã¹ããããã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ãUserServiceã§ãããå®éã«åãåãããè¡ãå®è£
ãUserServiceImplã¨ãªã£ã¦ãã¾ãã
FakeUserServiceã¯UserServiceImplã¨åããããªæ¯ãèãããããã¹ãç¨ã®è»½éå®è£
ã§ãã¦ã¼ã¶ã¼ã®è¿½å ãåå¾ã模æ¬ãã¦ãã¾ãã
ãããã£ã¦UserServiceã®å®è£
ã¨ãã¦DIã§å·®ãè¾¼ããã¨ã§ãUserServiceã«ä¾åãã¦ãã¦ããµã¼ãã¼ãèµ·åãããã¨ãªããã¹ãã§ãã¾ãã
æ¬ç©ã®DBããã§ã¤ã¯ãå«ãã ã³ã³ãã¼ãã³ãã®ä¾åé¢ä¿ãå³ç¤ºããã¨ä¸ã®ããã«ãªãã¾ãã

kintoneãã¼ã ã®ãã¹ãã«ã¯ä»ã¾ã§åä½ãã¹ããçµåãã¹ã (å é¨APIãã¹ãã®ã¿)ãSeleniumã使ã£ããã¹ããããã ããã«ä»åæ°ããæ¬ç©ã®DBããã§ã¤ã¯ã使ã£ãã¯ã©ã¹ã®ãã¹ããå ããã¾ããã ãããã£ã¦ãã¹ããæ¸ãéã«ã©ã®åºåã®ãã¹ãã§æ¸ããã¨ãã鏿è¢ãå¢ãããã¨ã«ãªãã¾ãã ãã¹ãã®å§¿ã ããè¦ãã¨åä½ãã¹ãã«è¦ãã¾ãããæ¬ç©ã®DBã¨çµåããã®ã§åºåã¨ãã¦ã¯çµåãã¹ãã«ãªããã¨æãã¾ãã ã¾ããkintoneã®ãµã¼ãã¼ãèµ·åããªãã¦æ¸ãã®ã§ãå é¨APIãã¹ããSeleniumãã¹ãããã軽éã«ãªãã¾ãã ããã§ãSeleniumãã¹ãã¯kintoneã®ãµã¼ãã¼ãä¾åããããã«ã¦ã§ã¢çãèµ·åããã¦ãã©ã¦ã¶ããã¢ã¯ã»ã¹ãããã¹ãã§ã å é¨APIãã¹ãã¯Seleniumãã¹ãã¨åãããµã¼ãã¼ãä¾åããããã«ã¦ã§ã¢çãèµ·åããã¾ããkintoneã®å é¨APIãå¼ã³åºãã¦ãã®æ¯ãèãã確èªãããã¹ãã«ãªãã¾ãã
å°å ¥ã®èæ¯
ãã®ãããªæ°ãããã¹ãã®ä»çµã¿ãå°å ¥ããã®ã¯è¨å¤§ãªéã¨ãªã£ãSeleniumãã¹ãããªãã¨ãããããã§ãã kintoneãã¼ã ã®éçºããã»ã¹ã§ã¯æ°ããæ©è½ã追å ãããã¨ã«ã ãã®æ©è½ã®ã¦ã¼ã¶ã¼ã¹ãã¼ãªã¼ãç´æ¥ä¿è·ã§ããSeleniumãã¹ãã追å ããããã«ãªã£ã¦ãã¾ãã ãããããªãªã¼ã¹ãã10年以ä¸çµéããSeleniumãã¹ãã®æ°ã大ãããã®ã«ãªã£ã¦ãã¾ãã ãã®ãããã¹ãã®å®è¡æéãé·ããªã£ã¦ãããéçºããã»ã¹ã«éãã®ãããã£ã¦ãã¦ãã¾ãã ããã§ä»£æ¿ææ®µã®ä¸ã¤ã¨ãã¦ãä»åç´¹ä»ããæ¬ç©ã®DBããã§ã¤ã¯ã使ã£ããã¹ãã調ã¹ã¦ãã¾ããã
æ¬ç©ã®DBããã§ã¤ã¯ã使ã£ããã¹ãã¯ã Googleã®ã½ããã¦ã§ã¢ã¨ã³ã¸ãã¢ãªã³ã°ã¨ããæ¬ãåèã«ãã¦ãã¾ãã ããã®ããæã ã¯ãæ¬ç©ã®ãªãã¸ã§ã¯ããé«éã§æ±ºå®æ§ã§ããéãã¯ã ã¢ãã¯ãªãã¸ã§ã¯ããããæ¬ç©ã®ãªãã¸ã§ã¯ãã使ããã¨ã好ãå¾åãããã1ãã¯ããã Googleã®ã½ããã¦ã§ã¢ã¨ã³ã¸ãã¢ãªã³ã°ã«ã¯åèã«ãªãã¢ã¤ãã£ã¢ãæ°å¤ãè¼ã£ã¦ãã¾ããã ãã§ã¤ã¯ã«ã¤ãã¦ã詳ããç´¹ä»ããã¦ãã¾ãã ãã®æ¬ã¯kintoneãã¼ã ã®åå¼·ä¼ã§èªãã æ¬ã§ãèªãã å¾ã«æå¿ã§éã¾ã£ã¦å°å ¥ãç¶ãã¦ãã¾ããã
ã¾ãåä½ãã¹ãã®èãæ¹/ä½¿ãæ¹ã¨ããæ¬ãåèã«ãªãã¾ããã ã管çä¸ã«ããä¾åã«å¯¾ãã¦ã¯å®éã®ã¤ã³ã¹ã¿ã³ã¹ã使ãããã«ãã管çä¸ã«ãªãä¾åã«å¯¾ãã¦ã¯ã¢ãã¯ã使ãããã«ãã¾ããããã2ã¨ãããªã©ã Googleã®ã½ããã¦ã§ã¢ã¨ã³ã¸ãã¢ãªã³ã°ã¨ä¼¼ããããªä¸»å¼µããªããã¦ãã¾ããã ã¾ããããããªãããã»ã¨ãã©ã®ã¢ããªã±ã¼ã·ã§ã³ã«ã¯ãã¢ãã¯ã«ç½®ãæããã¹ãã§ã¯ãªãããã»ã¹å¤ä¾åãåå¨ãã¾ãããã®ä¾åã¨ã¯ãã¼ã¿ãã¼ã¹ã®ãã¨ã§ããã3ã¨ããè¨è¼ããã£ãã®ã¨ãæ¬ç©ã®DBã¨çµåããçµåãã¹ããã³ã¼ãã¬ãã«ã§æ¸ããã¦ããããããã¯kintoneã§ã®æ¸ãæ¹ã«ã¤ãªããã¾ããã
ã¡ãªããã¨ãã¡ãªãã
æ¬ç©ã®DBããã§ã¤ã¯ã使ã£ããã¹ãã®ã¡ãªããã¨ãã¡ãªãããç´¹ä»ãã¾ãã
ä¸çªã®ã¡ãªããã¯ãã¹ãã«é¢ä¿ãªã夿´ã§å£ãã«ããã¨ãããã¨ã§ãã
RecordServiceã®ãã¹ããè¦ãã°ãããããã«ã
å
é¨å®è£
ããã¹ãã³ã¼ãã«ã¾ã£ããç¾ãã¦ããªãã¨è¨ã£ã¦ã大ä¸å¤«ã«æãã¾ãã
ãããã£ã¦ããã¹ãã«é¢ä¿ãªãå
é¨å®è£
ã®ã¿ã®å¤æ´ã«å¼·ããªã£ãã¨èãã¦ãã¾ãã
䏿¹ãä»ã¾ã§RecordSerivceã®ãããªDBã«ã¢ã¯ã»ã¹ãããããªã¯ã©ã¹ããã¹ãããæã¯ã
ä¸ã®ãããªã¢ãã¯ãä½¿ãæ¸ãæ¹ããããã¾ããã§ããã
@Test public void testAddRecord() { // Setup: ã¢ããªãæºå AppRow appRow = makeDummyAppRow(1L); doReturn(appRow).when(appRepository.getById(1L)) List<FieldRow> fieldRows = makeDummyFieldRows(); doReturn(fieldRows).when(fieldRepository.listByAppId(1L)) // Setupãç¶ã // ... // Exercise: ã¬ã³ã¼ãã追å recordService.addRecord(app, user.getId(), List.of(Field.singleLineText("æåå__1è¡_", "ãããã¤"))); // Verify: ã¬ã³ã¼ãã追å ããããç¢ºèª verify(recordRepository).insert(any(), recordCaptor.capture()); RecordRow record = recordCaptor.getValue(); assertThat(record.getValue("æåå__1è¡_")).isEqualTo("ãããã¤"); }
AppRepositoryãFieldRepositoryãªã©ã®ãã¹ãã¨é¢ä¿ãªãã¯ã©ã¹ããã¹ãã³ã¼ãã«ç¾ããããã
ãã¹ãã«é¢ä¿ãªãã¨ããããã®ã¯ã©ã¹ã夿´ããã¨å£ãããã¨ãããã¾ãã
ç§ãããæ©è½è¿½å ã§ã¡ã½ããã®å¼æ°ãå¢ããä¿®æ£ããããã¨ã§ã¡ã½ããå¼ã³åºãã®ã¢ãã¯ã䏿ã«å£ãã
ãããç´ãããã«ã¢ãã¯ã«ããã¼å¼æ°ãå¢ããä¿®æ£ã大éã«è¡ãç¶æ³ã«ãªã£ã¦ãã¾ã£ããã¨ãããã¾ãã
å ãã¦ããã¹ãã®ã»ããã¢ããå¦çãAppRepositoryãªã©å
é¨ã¯ã©ã¹ãåä½ã¨ãã¦æ¸ããããããããã¹ããçè§£ããã®ãé£ããæãã¾ãã
ä¾ãã°AppRepositoryã®getByIdã®è¿ãå¤ãè¨å®ããã¨ãã¦ãããã«ãã£ã¦ã©ãããç¶æ³ãä½ãããã®ããçè§£ããã®ã¯å®¹æã§ã¯ãªãã¨æãã¾ãã
æ¬ç©ã®DBã使ãã¨å
é¨å®è£
ããã¹ãã³ã¼ãã«ç¾ããªãããããã®ãããªãã¨ã¯èµ·ããã¾ããã
ããã«ãæ¬ç©ã®DBããã§ã¤ã¯ã使ããã¹ãã¯æ¬çªã«è¿ãç¶æ³ã§ã®ãã¹ãã«ãªãããã ä¿¡é ¼æ§ãååããã®ã§ã¯ãªããã¨èãã¦ãã¾ãã ãã¨ãã°ä¸è¨ã®ãããªã¢ãã¯ã使ãå ´åã¯ããã®IDã§ãã®ã¡ã½ãããå¼ã³åºããããã®å¤ãè¿ãã¨ããããã«ã ãã®ã¡ã½ããã«ä½ããã®åæãä¸ããä¸ã§ãã¹ããããã¨ãããã¨ã«ãªãã¾ãã ãããããã®åæãçã§ããã¨ç¢ºèªããããã¨ã¯ç¨ã§ããã¨æãã¾ããã ç¥ããªãéã«æãç«ããªããªã£ã¦ãã¾ãå¯è½æ§ãããã¾ãã
@Test public void testAddRecord() { AppRow appRow = makeDummyAppRow(1L); // AppRepositoryããã®æ¯ãèãããããã¨ã¯ç¢ºèªæ¸ã¿ï¼ doReturn(appRow).when(appRepository.getById(1L)); List<FieldRow> fieldRows = makeDummyFieldRows(); // FieldRepositoryããã®æ¯ãèãããããã¨ã¯ç¢ºèªæ¸ã¿ï¼ doReturn(fieldRows).when(fieldRepository.listByAppId(1L)); // ... }
æ¬ç©ã®DBã使ãå ´åã¯ç¹ã«ãã®ãããªåæãããã¾ããã ãã§ã¤ã¯ã使ã£ãå ´åã§ããã§ã¤ã¯ã®ãã¹ã (å¾è¿°) ã«ãããã®æ¯ãèãã¯çã§ããã¨ç¢ºèªã§ãã¦ããã®ã§ã çãã©ãã䏿ãªåæã¯ããã¦ããªãã¨æãã¾ãã ãã®ããã«å·®åãå°ãªããã¨ããæ¬çªã¨ãã¹ãæã§ç¶æ³ãè¿ããªã£ã¦ãããä¿¡é ¼æ§ãããé«ãã¨è¨ããã®ã§ã¯ãªããã¨æãã¾ãã
以ä¸ã®2ç¹ã®ã¡ãªããããã æ¬ç©ã®DBããã§ã¤ã¯ã使ã£ãæ°ãããã¹ãã¯å é¨APIãã¹ããSeleniumãã¹ãã®ä»£æ¿ææ®µã¨ã§ããããã«èãã¦ãã¾ãã ãã®ãã¨ã«ã¤ãã¦ã¯ä»å¾ããã«æ¤è¨¼ãé²ãããã¨æãã¾ãã
ãã®ã»ãã«ãå人çã«ãããªã¨æãã¦ãããã¨ã¯ããã¹ããããã¡ã½ãããä»ã®å
¬éã¡ã½ãããããçè§£ã§ããã¡ã½ããã®çè§£ãæ·±ã¾ããããªç¹ã§ãã
æ¬ç©ã®DBã使ã£ããã¹ãã§ã¯addRecordããã¨ãã®å¾ã¯listByIdsã§ããã¨æ¸ãã¦ããã¾ãã
ããã¯ã¤ã¾ããã¬ã³ã¼ãã追å ããã¨ã¯è¿½å å¾ã«listByIdsãå¼ã¹ããã¨ã ãã¨ã
ãã¹ããããã¡ã½ãããä»ã®å
¬éã¡ã½ãããéãã¦çè§£ã§ãããã«æãã¾ãã
䏿¹ã®ã¢ãã¯ã使ã£ããã¹ãã§ã¯addRecordã¯ãã®æä¸ã«RecordRepository#insertãããã¨æ¸ãã¦ããã¾ãã
ããã¯ç²åº¦ã®å¤§ããªè¿½å ã¡ã½ãããç²åº¦ã®å°ããªè¿½å ã¡ã½ãããå¼ãã§ãããã©ãããæ¤è¨¼ãã¦ããã ãã«ãªã£ã¦ããã
ãã¬ã³ã¼ãã追å ããã¨ã¯ã©ããããã¨ãããç¾ãã¦ãªãããã«æãã¦ãã¾ãã
ãã¡ãªããã¨ãã¦ã¯æ¬ç©ã®DBã使ããã¨ã«ãã£ã¦ä¸å®å®ã«ãªã£ããã ãã®ãããªãã¹ãããã 追å ããã ãã§ã¯ä»ãããå®è¡æéãé·ããªãã®ã§ã¯ãªããã¨ãã£ããã¨ãæãããã¾ãã ä¸å®å®ã«ãªããã¨ã«é¢ãã¦ã¯ãMySQLã«ã¯åæçã«ã¢ã¯ã»ã¹ãããã¨ãMySQLèªä½ããã¹ãæã§ãå®å®ãã¦åãã¦ãããã¨ãããä»ã®ã¨ããã¯åé¡ã«ãªã£ã¦ããã¾ããã å®è¡æéãé·ããªããã¨ã«é¢ãã¦ã¯ããã®ãã¹ãã®å°å ¥ãã¾ã å§ã¾ã£ãã°ãããªãããããããæ³¨è¦ãããã¨æã£ã¦ãã¾ãã ä»®ã«é ããªã£ããH2ãªã©ã®è»½éDBã使ã£ãã並ååã試ãããã¹ãã®æ§æãèãç´ããªã©ããããã¨èãã¦ãã¾ãã
ãã§ã¤ã¯ã®ãã¹ã
åè¿°ããããã«ããã§ã¤ã¯ã®æ¯ãèããæ¬ç©ã¨ããã¦ããã¨ãã¯ã©ã¹ã®ãã¹ãã¨ãã¦ä¸ååã§ãã
ããã§ããã§ã¤ã¯ãæ¬ç©ã®ãµã¼ãã¹ã¨åçã«æ¯ãèããã¨ã確èªããããã«ããã§ã¤ã¯ã«ããã¹ããæ¸ãã¦ãã¾ãã
å
ã»ã©ã®FakeUserServiceã«ããgetUserByIdã®ãã¹ãã¯ä»¥ä¸ã®ããã«ãªã£ã¦ãã¾ãã
class FakeUserServiceTest { @Nested class GetUserById { @Inject private UserServiceImpl userServiceImpl; private UserV1Client client = new UserV1Client(); @Test void notFake() throws Exception { // ã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ã®DBã®åæå TestDatabaseUtil.replace(init, "dump.sql"); // ã¦ã¼ã¶ã¼è¿½å APIãå©ç¨ãã¦ã¦ã¼ã¶ã¼ã追å String code = "user1"; client.usersPost(code); long userId = client.usersGet(code); assertGetUserById(userId, userServiceImpl); } @Test void fake() { FakeUserService fakeMiddleUserService = new FakeUserService(); User user = fakeMiddleUserService.registerUser("user1"); assertGetUserById(user.getId(), fakeMiddleUserService); } private void assertGetUserById(long userId, UserService userService) { assertThat(userService.getUserById(userId).code()).isEqualTo("user1"); } } }
fakeããã§ã¤ã¯ã使ã£ããã¹ããnotFakeãå®éã®ãµã¼ãã¹ã使ã£ããã¹ãã«ãªã£ã¦ãã¦ãåæ¹ãåãassertGetUserByIdãå¼ã³åºãã¦ãã¾ãã
assertGetUserByIdã§ã¯ãã¦ã¼ã¶ã¼ã追å ããã¦ããç¶æ
ã§ãã¦ã¼ã¶ã¼IDããgetUserByIdã使ã£ã¦ã¦ã¼ã¶ã¼ãåå¾ã§ãããã確èªãã¦ãã¾ãã
ãã®ããã«getUserByIdã確èªããã¡ã½ãããå
±éåãããã¹ãç¨ã®ãã§ã¤ã¯ã¨æ¬çªç°å¢ã§ä½¿ãå®è£
ã®ããããããå¼ã³åºããã¨ã§ã両è
ã®æ¯ãèããä¸è´ãããã¨ã確ããã¦ãã¾ãã
assertGetUserByIdã§åæã¨ãªã£ã¦ããã¦ã¼ã¶ã¼ã追å ããã¦ããç¶æ
ã®ä½ãæ¹ã«ã¤ãã¦ã
notFakeã§ã¯æ¬çªç°å¢ã§ä½¿ãã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ã®æ¯ãèãã®ç¢ºèªã«ãªãããã
ãã¹ãæã«å®éã«ãµã¼ãã¹ãç«ã¡ä¸ãã¦ã¦ã¼ã¶ã¼ã追å ãã¦ãã¾ãã
UserServiceã¯kintoneãããµã¼ãã¹ã«ã¢ã¯ã»ã¹ããããã®ã¤ã³ã¿ã¼ãã§ã¤ã¹ã«ãªã£ã¦ãããããã¦ã¼ã¶ã¼ã追å ããã¡ã½ãããããã¾ããã
ããã§ç«ã¡ä¸ããã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ã«å¯¾ãã¦ã¦ã¼ã¶ã¼è¿½å APIãå®è¡ãã
ã¦ã¼ã¶ã¼ã追å ããã¦ããç¶æ
ãä½ã£ã¦ãã¾ãã
䏿¹ã®fakeã§ã¯FakeUserServiceã«ããregisterUserã¡ã½ããã«ãã£ã¦ã¦ã¼ã¶ã¼ã追å ããã¦ããç¶æ
ãæ¨¡æ¬ãã¦ãã¾ãã
ãã§ã¤ã¯ããã¹ãããéã®ã³ã³ãã¼ãã³ãã®ä¾åé¢ä¿ãå³ç¤ºããã¨ä¸ã®ããã«ãªãã¾ãã

ãã§ã¤ã¯ã®ãã¹ããæ¸ããå¾ã§æ°ã¥ãããã¨ã¯ãUserServiceã®ãããªæ©è½ãæä¾ããå¥ãµã¼ãã¹ã¸ã®ä¾åãããããããç¶æ
ã«ãã§ã¤ã¯ã广ãçºæ®ãããã ãªã¨ãããã¨ã§ããã
RecordServiceã§ã¯ç¾ç¶ã¯UserServiceãããã«ããä¾åãããã¾ããããä»å¾å¥ãµã¼ãã¼ã§ç¨¼åãããµã¼ãã¹ãå¢ãã¦ãããã£ããµã¼ãã¹ã«ä¾åãå¢ããããããã¾ããã
// æ¬ç©ã®ãµã¼ãã¹ã使ãå ´å class RecordServiceTest { @Inject private UserService userService; // kintoneå¤ã«ããã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ @Inject private FooService fooService; // kintoneå¤ã«ããä½ããã®ãµã¼ãã¹foo @Inject private BarService barService; // kintoneå¤ã«ããä½ããã®ãµã¼ãã¹bar @Inject private BazService bazService; // kintoneå¤ã«ããä½ããã®ãµã¼ãã¹baz // ... }
ãã®ããã«ä¾åããå¥ãµã¼ãã¹ãå¢ãã¦ããç¶æ³ã«ããã¦ãã¹ããããã«ã¯ã æ¬ç©ã®DBã使ã£ããã¹ãã®ããã«æ¬ç©ã®ãµã¼ãã¹ã稼åããã¦æ¥ç¶ãã«ããå½¢ã®ãã¹ãã«ãããE2Eãã¹ãã«ããçã®ææ®µãããã¾ããã ã©ã¡ãã«ãã¦ãå°é£ã«ãªãã¨æãã¾ãã ã¨ããã®ããã©ã¡ãã®ããæ¹ããã¹ãå®è¡æã«ä¾åãããµã¼ãã¼ããã¹ã¦åæã«ç¨¼åããã¦ããå¿ è¦ãããããã§ãã ä¾åãããµã¼ãã¹ãã¹ã¦ãåæã«å®å®ãªç¶æ ã«ãã¦ãããªãã¨ãã¹ãèªä½ãå®å®ããªããªããã¨ãããåãµã¼ãã¼ã®ã¡ã³ããã³ã¹ã³ã¹ããå¢å¤§ããã¨æãã¾ãã ããã¯ä¾åãããµã¼ãã¹ãå¢ããã¨ããæ·±å»ã«ãªãã¾ãã
ãã§ã¤ã¯ã使ãã¨ãã®ãããªåææ§ãæé¤ã§ããã¡ã³ããã³ã¹ã®ã³ã¹ããæããããããã«æãã¾ãã æ©è½é¢ã«ããã¦ã¯ããã¹ã対象ã¨ãªãã¯ã©ã¹ã¯æ¬çªã§ç¨¼åãããµã¼ãã¹ã«ä¾åãã¦ããããã§ãªãã ãã®ãµã¼ãã¹ã®æ¯ãèãã«ä¾åãã¦ããã¨èãããã¾ãã ãã§ã¤ã¯ã¯æ¬ç©ã®ãµã¼ãã¹ã¨åçã«æ¯ãèããã¨ããã¹ãæ¸ã¿ã§ããæ©è½é¢ããã¯ãã®æ¯ãèãã«åºå¥ãã¤ããªããªããããæ¬ç©ã®ä»£ããã«ãã¹ãã«å©ç¨ãããã¨ã¯åé¡ãªãã¨æãã¾ãã ããã¨æ¬ç©ã®ãµã¼ãã¹ã«ä¾åããªããªãã®ã§ããã¹ãæã«ã¯ä¾åããåãµã¼ãã¹ã稼åããå¿ è¦ã¯ããã¾ããã ã¾ãããã§ã¤ã¯ã®ãã¹ãã¯ãã§ã¤ã¯ããåãµã¼ãã¹æ¯ã«å®è¡ã§ããããã稼åãå®å®åãåå¥ã«è¡ããã¨ãã§ãã¾ãã ãããã£ã¦åææ§ãæé¤ã§ãããã¹ãã®ã¡ã³ããã³ã¹ã³ã¹ãã®å¢å¤§ãé²ããã¨ã«ç¹ããããã«æãã¾ãã ãã®ãã¨ã¯ç¾æ®µéã§ã¯æ¨æ¸¬ã®åãåºã¦ããªããããä»å¾ãã§ã¤ã¯ããã§ã¤ã¯ã使ã£ããã¹ããå¢ãã¦ãã£ãéã«ã¯ç¢ºèªãããã¨æãã¾ãã
ä»å¾ã®èª²é¡ã¨å±æ
ä»å¾ã®èª²é¡ã¨ãã¦ã¯ç¬¬ä¸ã«ãæåã«è¨åããéãSeleniumãã¹ãã®ä»£æ¿ã¨ãã¦ä½¿ã£ã¦ã¿ããã¨ã§ãã kintoneãã¼ã ã¯ä»ã¾ã§Seleniumãã¹ããåä½ãã¹ãã«ã¤ãã¦ã¯é²ãã§ãã¹ããæ¸ãã¦ãã¾ããã ããããä»åå°å ¥ãããã¹ãã®åºåã§ããçµåãã¹ãã«é¢ãã¦ã¯ä»ã®ãã¹ãã»ã©å å®ãã¦ãããããã¦ãã¦ãèç©ããã¦ããªãã¨ããç¾ç¶ã§ãã ä»åå°å ¥ããæ¬ç©ã®DBã使ã£ãããã§ã¤ã¯ã使ã£ããã¹ãããã¢ãã¯ã使ãåä½ãã¹ã以å¤ã«ãæ¸ãæ¹ãããã¾ããããããã®å卿ããããã¾ããã ãããã£ã¦çµåãã¹ãã«ã¤ãã¦å¦ç¿ããåºåæ¯ã«å¹çãããã¹ããé åãã¦ããããã¨æãã¾ãã
ã¾ããã§ã¤ã¯ã®ããæ¹ã«ã¤ãã¦ã課é¡ãæãã¦ãã¾ãã ä¾ãã°ãã§ã¤ã¯ã®ãªã¼ãã¼ã«ã¤ãã¦ããã§ã¤ã¯ãåèã«ããGoogleã®ã½ããã¦ã§ã¢ã¨ã³ã¸ãã¢ãªã³ã°ã§ã¯ãµã¼ãã¹ãææãã¦ãããã¼ã ããã§ã¤ã¯ãå®è£ ããã¨ãªã£ã¦ãã¾ãã ããããç¾ç¶ã§ã¯kintoneã§å©ç¨ãã¦ãããã§ã¤ã¯ãã¡ã³ããã³ã¹ãã¦ããã®ã¯æ¬ç©ã®ãµã¼ãã¹ã®ãªã¼ãã¼ã§ã¯ãªãkintoneãã¼ã ã«ãªã£ã¦ãããããã¾ã§å°éã§ãã¦ãã¾ããã ããã¯ãã§ã¤ã¯ã®å°å ¥ãã¾ãkintoneãã¼ã å ã ãã§å°ããå§ããããã§ãã ä»å¾ãã§ã¤ã¯ã使ã£ããã¹ããåºããããã¹ãã®ä¸ã¤ã¨ãã¦ç¢ºç«ãããªã©ã®ã¿ã¤ãã³ã°ã§ã移管ãèãã¦ãããã®ããããã¾ããã
ãã§ã¤ã¯ã®ããæ¹ã«ã¤ãã¦ã¯ä»ã«ããæ¬ç©ã使ãããã§ã¤ã¯ã使ããã®å¤æãã¾ã ææ¢ãã¨ãããã¨ãããã¾ãã ä»ã®ã¨ããã¯kintoneã®æ©è½å®è£ ã®ä¸é¨ã¨ãªã£ã¦ãããã®ã¯ãã®ã¾ã¾ä½¿ãã kintoneãã¼ã 以å¤ãã¡ã³ããã³ã¹ãã¦ãããµã¼ãã¹ã¯ãã§ã¤ã¯ãã®ããã«ãªã£ã¦ããã¨æãã¾ãã
åè¿°ããããã«kintoneãå©ç¨ããDBã«ã¤ãã¦ã¯æ¬ç©ãç¨ãã¦ãããç¾ç¶ã¯å¤§ä¸å¤«ããªã¨ããããã«èãã¦ãã¾ãã kintoneã®åä½ãã¹ãã¯Github Actionsã使ã£ã¦åããã¦ãããMySQLããµã¼ãã¹ã³ã³ããã¨ãã¦ç°¡åã«ç«ã¡ä¸ãããã¨ãã§ãããã¹ãæã«ããã¦ãå®å®ç¨¼åãã¦ããã¾ãã kintoneãå©ç¨ããDBã¯kintoneãã¼ã ã§ç®¡çãã¦ããDDLãã¡ã¤ã«ãã©ãã«ããããªã©ãææ¡ã§ãã¦ãã¾ãã ã¾ãããã®DBã¯kintoneã®æ©è½å®è£ ã®ä¸é¨ã§ãããããJavaã¨ã¾ã¨ãã¦ãã¹ãããã®ãçè§£ã¯ã§ããã®ããªã¨æãã¾ãã
䏿¹ã§ãã§ã¤ã¯ã使ã£ãUserServiceã«ã¤ãã¦ã¯ããã§ã¤ã¯ã®ã»ããé½åãããããã«æãã¾ãã
ã¢ã¯ã»ã¹ããå
ã®ã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ã¯å¥ãã¼ã ã«ãã£ã¦ã¡ã³ããã³ã¹ããã¦ããã
ä»®ã«æ¬ç©ã®ãµã¼ãã¹ãkintoneã®ãã¹ãã§ã使ãå ´åãèªåéã詳ãããªããµã¼ãã¹ãç«ã¡ä¸ããªãã¨ãããªãããã
ãã¹ãã®ç°å¢æ§ç¯ã大å¤ã«ãªãããã«æãã¾ãã
ããã«ãµã¼ãã¹ãå©ç¨ããã¦ã¼ã¶ã¼ã®å±æ§ãkintoneã¨éãã¾ãã
ãã®ããã«éçºãã¦ãããã¼ã ã®éããããã¹ãã®ç°å¢æ§ç¯ã大å¤ã«ãªããããªæ¸å¿µã
ãµã¼ãã¹ãæä¾ãã¦ããæ©è½ã®éããªã©ãããã§ã¤ã¯ãéãã¦åé¢ãã¦ãã¾ãã
ã¨ããã§ãã¦ã¼ã¶ã¼ç®¡çãµã¼ãã¹ã®ãããªå¥ãã¼ã ã«ãã£ã¦ã¡ã³ããã³ã¹ãã¦ãããµã¼ãã¹ã¸ã®ä¾åã¯ã åä½ãã¹ãã®èãæ¹/ä½¿ãæ¹ã«ããã管çä¸ã«ãªãä¾åã§ãããã¢ãã¯ã使ãã¿ã¤ãã³ã°ã§ãã ä»åãã§ã¤ã¯ã®å°å ¥ã«ãã£ã¦ããã®ã¿ã¤ãã³ã°ã§ã¢ãã¯ã®ä»ã«ãã§ã¤ã¯ãé¸ã¶ãã¨ãã§ããç¶æ³ã«ãªã£ã¦ãã¾ãã åä½ãã¹ãã®èãæ¹/ä½¿ãæ¹ã«ã¯ãã§ã¤ã¯ã«ã¤ãã¦ã®è¨åã¯ãªãã§ããããã§ã¤ã¯ãé¸ãã§ãåé¡ãªãã®ããªã¨æãã¾ãã
屿ã¨ãã¦ã¯ããã§ã¤ã¯ã¨ã³ã¼ãåå²ã¨ã§ç¸ä¹å¹æãçã¾ãããã«æãã¦ãã¾ãã
kintoneãã¼ã ã§ã¯ã³ã¼ãåå²ãé²ãã§ãããç¾å¨ã¯ã¢ããªè¨å®æ©è½ãkintoneå
ã§ããç¨åº¦ç¬ç«ããé åã¨ãã¦æ½åºããã¤ã¤ããã¾ãã
ãã®çµæã¨ãã¦ã¢ããªè¨å®ãµã¼ãã¹(AppSettingsService)ã®ãããªãã®ãkintoneå
ã«ã§ãããã§ãã
ããã«ãã®ãã§ã¤ã¯(FakeAppSettingsService)ãä½ããã¨ã§ãã¹ãã³ã¼ããããæ¹åãããã®ã§ã¯ãªããã¨èãã¦ãã¾ãã
ä¾ãã°ãæåã«èª¬æããRecordServiceã®ãã¹ãã¯æ¬¡ã®ããã«æ¸ããããã«æãã¾ãã
class RecordServiceTest { @Inject private FakeUserService fakeUserService; @Inject private FakeAppSettingsService fakeAppSettingsService; @Inject private RecordService recordService @BeforeEach public void testAddRecord() { // Setup // userã追å User user = fakeUserService.registerUser("user"); // ã¢ããªã追å App app = fakeAppSettingsService.registerApp("App", List.of(SingleLineTextField.of("æåå__1è¡_", "æåå (1è¡)"))); // Exercise: ã¬ã³ã¼ãã追å long recordId = recordService.addRecord(app, user.getId(), List.of(Field.singleLineText("æåå__1è¡_", "ãããã¤"))); // Verify: ã¬ã³ã¼ããåå¾ List<Record> records = recordService.listByIds(app, user.getId(), List.of(recordId)); assertThat(records.get(0).getValue("æåå__1è¡_").orElseThrow()).isEqualTo("ãããã¤"); } }
FakeAppSettingsServiceã¯ã¢ããªè¨å®æ©è½ã®ãã§ã¤ã¯ã§ãregisterAppãå®è¡ãããã¨ã§ã¢ããªã使ãããã¨ãã§ãã¾ãã
æ¬ç©ã®DBã使ã£ã¦ããæã§ã¯ã¢ããªãã¯ãããã使ãããã£ã¼ã«ãã追å ããããã¤ã¨ããæé ãè¸ãã§ãã¾ãããã
ãã§ã¤ã¯ã使ãã¨ä¸æ°ã«å®è¡ã§ããããã«è»½éå®è£
ãªã®ã§éããããã¾ãã
ãã¹ãã¨ãã観ç¹ã§ã¯ãã¢ããªãã©ã®ããã«ä½ããã¦ããã®ãã¯é¢å¿ã®å¤ã§ã
ã¤ã¾ãã¯ã¢ããªãåå¨ãã¦ããç¶æ
ã«å°éãããããã°åé¡ããã¾ããã
ãªã®ã§ãããã£ãç¹ããããã¡ãã®æ¸ãæ¹ã®ã»ããçæ³çã§ã¯ãªããã¨æãã¾ãã
ã¾ãããã§ã¤ã¯ã使ãã¨ãã¹ãã¯ã¢ããªã®ç¶æ
ã«ã®ã¿ä¾åããããã«ãªããã¢ããªãã©ãä½ããã¨ããã¢ããªè¨å®æ©è½ã«ãä¾åããªããªãã¾ãã
ãã®ããã«ã¢ããªè¨å®æ©è½ã¸ã®ä¾åãæ¸ãã¨ãã¢ããªè¨å®æ©è½ã®æ©è½å¤æ´ããããããªãã®ã§ãªããã¨æãã¾ãã
ãªããregisterAppãããç¶æ
ã¨ãã¢ããªãã¯ãããã使ãããã£ã¼ã«ãã追å ããããã¤ã¨ããæé ãè¸ãã å¾ã®ç¶æ
ãä¸è´ãããã¨ã¯ã
FakeAppSettingsServiceã®ãã¹ãã§ç¢ºèªããæ³å®ã§ãã
ã¢ããªã®ä½æããã£ã¼ã«ã追å ãªã©ã®æ´æ°ã¯ãããããªã¡ã½ããã¨å調åä½ããã®ã§ã
ãã®ãã§ã¤ã¯ã®ãã¹ãã¯ããªã大å¤ã«ãªããã¨ãäºæ³ããã¾ãâ¦â¦ã
ã¾ã¨ã
æ¬ç©ã®DBããã§ã¤ã¯ã使ã£ãæ¬çªã«è¿ãç¶æ³ã§å®è¡ã§ãããã¹ããç´¹ä»ãã¾ããã kintoneãã¼ã ã®ãã¹ãã«ã¯ä»ã¾ã§åä½ãã¹ããå é¨APIãã¹ããSeleniumã使ã£ããã¹ãããã£ãã®ã§ããããã®ä¸ã«æ°ããå ããã¾ããã ããã¯Googleã®ã½ããã¦ã§ã¢ã¨ã³ã¸ãã¢ãªã³ã°ãåä½ãã¹ãã®èãæ¹/ä½¿ãæ¹ã¨ããæ¬ãåèã«ãã¾ããã æ¬ç©ã®DBããã§ã¤ã¯ã使ã£ããã¹ãã¯å é¨å®è£ ã®å¤æ´ã«å¼·ããSeleniumãã¹ãã¨åçã®ä¿è·ãåãã¦ãããããªæè§¦ãæ´ããããã«ãªã£ã¦ãã¾ãã ã¾ãã³ã¼ãåå²ã¨çµã¿åããããã¨ã§æ´ãªãæ¹åã«ãã¤ãªããããã§ãã ãã®ãã¹ãã¯æè¿ã§ããã°ãããªã®ã§ãä»å¾ãä½¿ãæ¹ãæ¢æ±ãã¦ãããã¨æã£ã¦ãã¾ãã