제출이 되는 경우/ 되지 않는 경우로 제출의 결과가 나뉜다.
되는 경우. 되지 않는 경우가 존재하기 때문에 프로그램의 정확성을 높히기위해서 에러를 얼른 고쳐야한다
해당 경우가 이 문제의 키포인트 같았다. 실제로 잘 작동하던 때도 있었으니까 말이다.
@SpringBootTest
@Import(TestConfiguration.class)
@Slf4j
public class LoadingAndEnterMethodTest {
@Autowired
MachineLoadingAndEnterZenput machineLoadingAndEnterZenput;
@Autowired
FoodLoadingAndEnterZenput foodLoadingAndEnterZenput;
@Test
@DisplayName("Machine Enter")
public void machineLoading(){
JSONObject machineMap = new JSONObject();
machineMap.put("mgrname", "띤또뚠");
JSONArray contents =new JSONArray();
JSONObject tempMap = new JSONObject();
tempMap.put("id","2");
tempMap.put("name","온도계(탐침1)" );
tempMap.put("temp","32");
JSONObject tempMap4 = new JSONObject();
tempMap4.put("id","54");
tempMap4.put("name","온도계(탐침2)" );
tempMap4.put("temp","31");
JSONObject tempMap5 = new JSONObject();
tempMap5.put("id","56");
tempMap5.put("name","온도계(표면1)" );
tempMap5.put("temp","33");
JSONObject tempMap2 = new JSONObject();
tempMap2.put("id","117");
tempMap2.put("name","워크인프리저");
tempMap2.put("temp","-3");
JSONObject tempMap3 = new JSONObject();
tempMap3.put("id","20");
tempMap3.put("name","스페셜티프리저1");
tempMap3.put("temp","-2");
contents.put(tempMap);
contents.put(tempMap4);
contents.put(tempMap5);
contents.put(tempMap2);
contents.put(tempMap3);
machineMap.put("customMachine", contents);
machineMap.put("time","PM");
log.info("map result = {}", machineMap.toString(2));
try {
Map<String, String> machine = machineLoadingAndEnterZenput.sendValueV2(machineMap.toString());
log.info(machine.toString());
} catch (Exception e) {
log.info(e.toString());
}
}
}
실제로 매장에서 사용하는 사이트를 쓸 수 없기 때문에 테스트페이지로 진행을 수행했다.
그럼 Config.java파일에 있는 configuration이 아닌 Test를 위한 독자적인 bean관리가 필요했다.
따라서
@org.springframework.boot.test.context.TestConfiguration
@EnableJpaRepositories(basePackages = "burgerput.project.zenput.repository")
class TestConfiguration {
@Bean
public MachineLoadingAndEnterZenputV2T machineLoadingAndEnterZenput() {
return new MachineLoadingAndEnterZenputV2T();
}
@Bean
public FoodLoadingAndEnterZenputV2T foodLoadingAndEnterZenput() {
return new FoodLoadingAndEnterZenputV2T();
}
}
위처럼 LoadingAndZentput 테스트 파일을 빈으로 주입받는 TestConfiguration을 만들었다.
Test HTML파일을 준비한다. 기존의 파일은 submit 버튼을 눌러도 아무것도 실행되지 않기 때문에 alert창을 띄워서 확인하도록 했다.
<script>
document.addEventListener("DOMContentLoaded", function() {
var submitForm = document.getElementById("submit_form");
if (submitForm) {
submitForm.addEventListener("click", function() {
alert("Submit form clicked!");
});
}
});
</script>
html하단에 submit을 Alert창이 뜨도록 설정했다.
이렇게 말이다.
그럼 headless를 주고 해당 화면을 캡쳐하도록 확인해보자
<div id="success_message" class="success-message" style="display: none;">성공</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
var submitForm = document.getElementById("submit_form");
var successMessage = document.getElementById("success_message");
if (submitForm) {
submitForm.addEventListener("click", function() {
successMessage.style.display = 'block';
});
}
});
</script>
Alert창을 띄운뒤에 캡쳐가 되지 않아서 버튼을 누르면 성공이라고 나타나게 설정했다.
그리고 MachineLoadingAndZenputTest파일에서 드라이버 로딩 시간을 120초로 증가시키고 Thread.sleep으로 강제로 쉬던 부분은 제거했다.
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(120), Duration.ofMillis(500));
JavascriptExecutor js = (JavascriptExecutor) driver;
// JavaScript 로드 완료 대기
wait.until(webDriver -> js.executeScript("return document.readyState").equals("complete"));
log.info("enver Food and rest 3000");
Thread.sleep(3000);
private void enterValue(WebElement field, ArrayList<Map<String, String>> machineMap, Map<String,String> resultMap) {
try {
//extract vaild id field
WebElement input = field.findElement(By.tagName("input"));
String id = input.getAttribute("field_id");
for (int i = 0; i < machineMap.size(); i++) {
Map<String, String> customMap = machineMap.get(i);
try {
if (id.equals(customMap.get("id"))) {
log.info("enter Map info {}", customMap);
input.sendKeys(customMap.get("temp"));
input.sendKeys(Keys.TAB);
// Thread.sleep(1000);
machineMap.remove(i);
break;
}
} catch (NullPointerException e) {
log.info("error message ={}", e);
//do nothing
} catch (ElementNotInteractableException e) {
log.info("ElementNotinteratable Excpetion error");
log.info(e.toString());
resultMap.put("result", "false");
}
}
} catch (Exception e) {
log.info("Error LoadFood={}", e.toString());
}
}
Machine: 성공!!!
현재 Food는 파일이 없어서 테스트를 못한다. 하지만 Machine과 로직이 똑같다… ㅠ 근데 왜 테스트는 되고 왜 서버에 올리면 되지 않는 걸까?…
혹시나 하는 마음에!!…
File screenshotAs = ((TakesScreenshot) driver).getScreenshotAs((OutputType.FILE));
File file = new File("/home/ubuntu/burgerput/img/zenputMachine"+ LocalDate.now()+ LocalTime.now()+".png");
FileUtils.copyFile(screenshotAs, file);
WebElement submitForm = wait.until(ExpectedConditions.visibilityOfElementLocated((By.id("submit_form"))));
submitForm.click();
log.info("Machine button Clicked");
log.info("quit the Driver ()");
driver.quit();
기존에는 버튼을 누르고 바로 driver를 종료했었다. 그렇다면 시간을 조금 준 뒤에 종료하게 된다면 어떻게 될까? 그렇다 제출을 하고 시간을 줘보는 것이야!!!!!!!!!!!!!!!!!!!!
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(120), Duration.ofMillis(500));
JavascriptExecutor js = (JavascriptExecutor) driver;
// JavaScript 로드 완료 대기
wait.until(webDriver -> js.executeScript("return document.readyState").equals("complete"));
...
File screenshotAs = ((TakesScreenshot) driver).getScreenshotAs((OutputType.FILE));
File file = new File("/home/ubuntu/burgerput/img/zenputMachine"+ LocalDate.now()+ LocalTime.now()+".png");
FileUtils.copyFile(screenshotAs, file);
WebElement submitForm = wait.until(ExpectedConditions.visibilityOfElementLocated((By.id("submit_form"))));
submitForm.click();
log.info("Machine button Clicked");
log.info("rest 5000 and quit the Driver ()");
Thread.sleep(5000);
enterValueV2 로직에 불필요한 Thread.sleep을 모두 제거했다.
그 후에 제출버튼을 클릭하고 5초 쉬도록 했다. 제출버튼을 클릭하고 그 다음 페이지의 정보가 나한테 없어서 지금은 이게 최선이다.
셀레니움을 사용해서 웹 사이트에 값을 제출하고 드라이버를 종료하면 제출이 완료되지 않을 가능성이 있다. 제출 버튼을 클릭한 후 웹 사이트가 응답하기 전에 드라이버를 종료했기 때문이다.
제출 버튼을 클릭한 후 서버의 응답을 기다려야한다!!!
웹 서버에게 단순히 보내고 끝이 아니다. 응답을 기다려야한다!!!
언제나 요청-응답 쌍임을 잊지말자. 요청-응답 요청-응답
Seleinum라이브러리에서 요청을 바로 보낸후 driver를 닫아버리면 서버의 응답을 받아버리기 전에 닫히므로 요청이 제대로 수행되지 않는 경우가 있다.