> For the complete documentation index, see [llms.txt](https://help.goorm.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.goorm.io/ko/edu-lecturer/04.quiz/marking-script.md).

# 채점 스크립트 작성하기

### 1. 나이트워치 (Nightwatch.js)

구름EDU에서는 웹 서비스/애플리케이션 개발 문제 혹은 HTML/CSS/JS 프로그래밍 문제는 \
**나이트워치** 라는 UI테스트 프레임워크를 활용하여 채점을 합니다. \
웹 관련 문제의 정확한 채점을 위해서는 **나이트워치** 라는 UI테스트 프레임워크에 익숙해져야 합니다.&#x20;

> [Nightwatch.js 공식 사이트](http://nightwatchjs.org/)

![](https://grm-project-template-bucket.s3.ap-northeast-2.amazonaws.com/lesson/les_sYDdt_1517887271694/1470056246360_image.png)

###

### 2. 채점 스크립트 작성해보기 #1

본 도움말에서 Nightwatch.js의 모든 기능과 API에 대해서 설명을 할 수는 없기에 \
공식 사이트에 있는 아래의 예제를 기준으로 개념적인 부분을 설명합니다.

```
module.exports = {
  'Demo test Google' : function (browser) {
    browser
      .url('http://www.google.com')
      .waitForElementVisible('body', 1000)
      .setValue('input[type=text]', 'nightwatch')
      .waitForElementVisible('button[name=btnG]', 1000)
      .click('button[name=btnG]')
      .pause(1000)
      .assert.containsText('#main', 'Night Watch')
      .end();
  }
};
```

1. `module.exports = {` : \
   node.js의 문법으로써 사용자 모듈을 만드는 과정입니다. `{` 이하로 할당되었기 때문에 여러 테스트 메소드를 가지는 객체가 될 것입니다.<br>
2. `'Demo test Google' : function (browser) {` : \
   테스트 케이스의 이름과 거기에 할당되는 테스트 메소드입니다. \
   이 코드에서는 'Demo test Google' 이라는 이름으로 작성이 시작되었습니다.<br>
3. `browser` : \
   Nightwatch.js 에서는 가상의 웹브라우저가 객체 형태로 각각의 테스트 메소드에 전달됩니다. \
   이 `browser`는 우리가 개념적으로 알고 있는 웹브라우저로서, 눈에 보이지는 않지만 \
   마치 웹브라우저처럼 동작하는 가상의 객체라고 이해하면 됩니다.<br>
4. `.url('http://www.google.com')` : \
   `.url()` 은 `browser` 객체에게 특정 웹사이트의 URL로 접속하게 만드는 메서드로써, \
   이 코드에서는 구글로 접속하게 하고 있습니다.<br>
5. `.waitForElementVisible('body', 1000)` : \
   웹페이지의 기본 골격을 담당하는 `body` 태그가 화면에 보여질(Visible) 때까지 \
   최대 '1초(=1000ms)간' 기다린다는 의미의 메서드입니다.<br>
6. `.setValue('input[type=text]', 'nightwatch')` : \
   화면에 보이는 요소 중에 `input` 태그요소이면서 그 속성이 `type=text`인 것을 찾아서 'nightwatch'라는 문자열 값을 입력하는 메서드입니다. \
   이 메서드는 결국 구글 첫 화면의 검색어 입력창에 'nightwatch'를 입력한 효과를 보여주게 됩니다.<br>
7. `.waitForElementVisible('button[name=btnG]', 1000)` : \
   5번째 라인과 동일한 메서드로서, 이번엔 `button` 태그요소 중 `name=btnG`인 것이 \
   화면에 나타날 때까지 최대 1초간 기다린다는 의미입니다.<br>
8. `.click('button[name=btnG]')` : \
   메서드 명인 `click()` 이라는 의미 그대로 해당 요소(`button[name=btnG]`)를 클릭합니다.<br>
9. `.pause(1000)` : 1초간 기다립니다.<br>
10. `.assert.containsText('#main', 'Night Watch')` : \
    `id` 속성 값이 `main`인 HTML DOM 요소를 찾아서 'Night Watch'라는 문자열이 \
    포함되어 있는지 확인합니다.<br>
11. `.end()` : \
    지금까지 가상의 브라우저와 상호작용하는 일련의 작업들을 그만하고 끝내겠다는 의미입니다.

자바스크립트 및 node.js 문법에 익숙해져야하고, 다소 복잡할 수 있지만 익숙해지면 쉽게 작성할 수 있는 것이 Nightwatch.js UI Testcase 입니다. 웹 서비스/애플리케이션이 실제로 동작한다고 가정하고 사용자의 행동을 기술하는 것이기 때문입니다. 위의 예에서는 서비스가 잘 만들어졌고, 원하는 대로 잘 동작하고 있는지 확인하는 부분이 바로 10번 라인입니다.<br>

### 3. 채점 스크립트 작성해보기 #2

나이트워치를 이용하여 정답 판정은 테스트가 실패(fail)하거나 에러(error)가 하나라도 발생하면 오답, \
그렇지 않으면 정답 판정을 내립니다. \
오답이 나타나는 대표적인 케이스들에 대하여 하단에 열거하겠습니다.

1. **browser.waitForElementVisible**(css\_셀렉터, 최대\_기다리는\_시간\_밀리세컨\_단위) : \
   설정한 DOM이 기다리는 시간 내에 보이지 않을 경우, 실패<br>
2. **browser.waitForElementPresent**(css\_셀렉터, 최대\_기다리는\_시간\_밀리세컨\_단위) : \
   설정한 DOM이 기다리는 시간 내에 존재하지 않을 경우, 실패<br>
3. **browser.waitForElementNotVisible**(css\_셀렉터, 최대\_기다리는\_시간\_밀리세컨\_단위) : \
   설정한 DOM이 기다리는 시간 내에 보이지 않은 상태가 되지 않으면, 실패.<br>
4. **browser.waitForElementNotPresent**(css\_셀렉터, 최대\_기다리는\_시간\_밀리세컨\_단위) : \
   설정한 DOM이 기다리는 시간 내에 존재하지 않은 상태가 되지 않으면 경우, 실패<br>
5. **browser.assert** : \
   `assert` 뒤에 이어지는 구문의 조건이 만족되지 않으면 실패.<br>

나이트워치 테스트 스크립트를 작성하다 보면, DOM을 지정해야 하는 경우가 많습니다. \
나이트워치 API에서 DOM을 지정하기 위해서는 CSS 셀렉터나, XML의 Xpath를 이용해야 하는데, \
여기 CSS 셀렉터에 대한 레퍼런스가 있습니다.

W3C는 월드 와이드 웹 컨소시움(World Wide Web Consortium)이라는 뜻으로, \
웹 표준을 개발하고 장려하는 조직입니다.

Mozilla는 최초의 그래픽 웹 브라우저인 모자이크의 대를 잇는 자유 소프트웨어 커뮤니티입니다. \
자바스크립트가 최초 적용된 넷스케이프 브라우저와도 연관이 깊습니다.

> [W3C CSS Selector Reference<br>](https://www.w3.org/TR/css3-selectors/#selectors)[Mozilla Developer Network CSS Selector Reference](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Selectors)

좀 더 깊은 이해를 위해 실제로 테스트 스크립트로 쓰이는 예제 스크립트 코드를 하단에 첨부했습니다.

해당 문제는 로그인 폼 처리하는 문제이며, 아래 스크립트 코드가 확인하는 기능은, \
로그인이 된 이후에는 로그인 폼이 보이지 않게 되는 기능입니다.

1. 사이트 접속
2. 페이지가 로딩되고, id값을 입력하는 input이 나타날 때 까지 기다림
3. id값 입력하는 input에 Anonymous라고 입력함.
4. 로그인 버튼 클릭
5. 잠시 기다림
6. form 태그가 보이지 않는지 확인

```
var site_url;
module.exports = {
  'case' : function (browser) {
    site_url = browser.globals.server_url; 
    browser
        .maximizeWindow()
        .url(site_url)
        .waitForElementVisible('body', 2000)
        .waitForElementVisible('#id', 2000)
        .setValue('#id', 'Anonymous')
        .click('#login')
        .url(site_url)
        .pause(200)
        .waitForElementNotPresent('form', 2000)
  }
};
```

1\~5번째 라인까지는 기본적으로 들어있는 템플릿 코드입니다. browser라는 객체의 메소드를 이용해서 \
테스트 케이스를 진행하면 됩니다. 라인 별로 설명을 하겠습니다.

1. `var site_url;` : \
   어떤 사이트로 접속할 지 URL을 저장하기 위한 변수의 선언부입니다.<br>
2. `module.exports = {` : \
   node.js의 문법으로써 사용자 모듈을 만드는 과정입니다. \
   `{` 이하로 할당되었기 때문에 여러 테스트 메소드를 가지는 객체가 될 것입니다.<br>
3. `'case' : function (browser) {` : \
   테스트 케이스의 이름과 거기에 할당되는 테스트 메소드입니다. \
   이 코드에서는 'case' 이라는 이름으로 작성이 시작되었습니다.<br>
4. `site_url = browser.globals.server_url;` :  \
   구름EDU에서 자동으로 실행되는 웹 서버의 주소는 `browser.globals.server_url`이라는 곳에 \
   그 값이 미리 들어가 있습니다. 따라서 비어있는 `site_url`에 채점하고자 하는 대상 웹서버 주소, \
   즉 수강자가 작성한 코드가 실행되는 웹 서버의 주소를 넣어주는 과정입니다.<br>
5. `browser` : \
   Nightwatch.js 에서는 가상의 웹브라우저가 객체 형태로 각각의 테스트 메소드에 전달됩니다. \
   이 `browser`는 우리가 개념적으로 알고 있는 웹브라우저로서, 눈에 보이지는 않지만 \
   마치 웹브라우저처럼 동작하는 가상의 객체라고 이해하면 됩니다.<br>
6. `.maximizeWindow()` : \
   [maximizeWindow라는 메소드](https://nightwatchjs.org/api/maximizeWindow.html#apimethod-page)는 테스트용 브라우저의 윈도우 화면을 최대화 하라는 뜻입니다. \
   화면이 작아서 웹 페이지가 모바일용 형태로 보인다던지 하는 예외상황을 막아줄 수 있습니다.<br>
7. `.url(site_url)` : [url이라는 메소드](https://nightwatchjs.org/api/url.html#apimethod-page)는 해당 url로 이동하라는 뜻입니다. <br>
8. `.waitForElementVisible('body', 2000)` : \
   [waitForElementVisible이라는 메소드](https://nightwatchjs.org/api/waitForElementVisible.html#apimethod-page)는 첫번째 파라메터인 body태그가 보일 때까지 \
   최대 2000밀리세컨(2초)동안 기다린다는 뜻입니다. \
   이 테스트 케이스에서 이 메소드는 해당 웹 url을 통해 접속을 하는데, 웹 페이지의 body 태그가 \
   로딩될 때까지 최대 2초동안 기다린다는 맥락을 가지고 있습니다. \
   만약 2초 내에 body 태그가 보이지 않으면, 이 테스트 케이스는 **실패**로 끝나게 됩니다.<br>
9. `.waitForElementVisible('#id', 2000)` : \
   8번째 라인의 메소드와 같으며, id값이 id인 태그를 최대 2초동안 기다린다는 뜻을 가지고 있습니다. \
   해당 문제는 id만 입력하여 로그인을 하는 문제이며, id값이 id인 태그는 사용자의 아이디를 입력하는 Text input태그입니다.<br>
10. `.setValue('#id', 'Anonymous')` : \
    [setValue라는 메소드](https://nightwatchjs.org/api/setValue.html#apimethod-page)는 #id라는 셀렉터, 즉 id값이 id인 태그에 'Anonymous'라는 문자열 값을 \
    입력하라고 하는 뜻을 가지고 있습니다. \
    만약 #id라는 셀렉터에 해당되는 DOM이 없다면 이 테스트 케이스는 **에러**로 끝나게 됩니다.<br>
11. `.click('#login')` : \
    [click이라는 메소드](https://nightwatchjs.org/api/click.html#apimethod-page)는 #login이라는 셀렉터, 즉 id값이 login태그를 클릭하라는 뜻을 가지고 있습니다. 만약 #login이라는 셀렉터에 해당되는 DOM이 없다면 이 테스트 케이스는 **에러**로 끝나게 됩니다.<br>
12. `.url(site_url)` : \
    url이라는 메소드는 7번째 라인의 내용과 같습니다.<br>
13. `.pause(200)` : \
    [pause라는 메소드](https://nightwatchjs.org/api/pause.html#apimethod-page)는 200 밀리세컨(0.2초)만큼 잠시 멈추라는 뜻을 가지고 있습니다. \
    웹 페이지가 랜더링 되는 시간을 기다리는 부분입니다.<br>
14. `.waitForElementNotPresent('form', 2000)` : \
    [waitForElementNotPresent라는 메소드](https://nightwatchjs.org/api/waitForElementNotPresent.html#apimethod-page)는 form 태그가 보이지 않게 될 때 까지 최대 2000밀리세컨\
    (2초)까지 기다린다는 뜻입니다. 로그인 한 뒤 form 태그가 보이지 않게 되는지 확인하는 부분입니다.

\
위와 같은 방식으로 채점 스크립트를 작성하면 되며, 좀더 자세한 API들을 알고 싶으면 \
나이트워치 공식 홈페이지의 API 레퍼런스를 참조하시면 됩니다.

> [Nightwatchjs API Reference](http://nightwatchjs.org/api)

<br>
