수색…
비고
Nightwatch는 Meteor 응용 프로그램에 대한 Acceptance 및 End-to-End 테스트를 v0.5 일 이후 제공하고 있으며 PHP에서 Spark to Blaze 및 React로 마이그레이션을 관리했습니다. 모든 주요 Continuous Integration 플랫폼이 포함됩니다. 추가 도움이 필요하면 다음을 참조하십시오.
앱 표면 영역
가장 기본적인 수준에서 수락 테스트는 근본적으로 닫힌 시스템의 입력 및 출력 테스트와 관련된 기본적으로 블랙 박스 테스트입니다. 따라서 수락 테스트에는 리소스 찾기, 데이터 읽기 및 데이터 쓰기와 같은 세 가지 필수 기능이 있습니다. 브라우저와 웹 애플리케이션의 경우이 세 가지 기능은 기본적으로 다음과 같이 요약됩니다.
- 웹 페이지 또는 애플리케이션보기로드
- 사용자 인터페이스 요소 검사 (예 : DOM)
- 이벤트 트리거 / 사용자 상호 작용 시뮬레이션
이것을 응용 프로그램의 표면 영역이라고합니다. 표면적 영역은 사용자가 보거나 경험하는 모든 것입니다. 그것은 블랙 박스 시스템의 외부입니다. 또한 사용자는 웹 브라우저를 사용하여 비디오 화면에서 최신 웹 응용 프로그램과 상호 작용하기 때문에 범용 리소스 로케이터 (URL) 및 뷰포트로 정의됩니다. 그래서 우리의 첫 번째 연습은 다음과 같은 것을 보게됩니다 :
module.exports = {
"Hello World" : function (client) {
client
// the location of our Meteor app
.url("http://localhost:3000")
// the size of the viewport
.resizeWindow(1024, 768)
// test app output
.verify.elementPresent('h1')
.verify.containsText('h1', "Welcome to Meteor!")
.verify.containsText('p', "You've pressed the button 0 times")
.verify.elementPresent('button')
// simulate user input
.click('button').pause(500)
// test app output again, to make sure input worked
.verify.containsText('p', "button 1 times")
// saving a copy of our viewport pixel grid
.saveScreenshot('tests/nightwatch/screenshots/homepage.png')
.end();
}
};
사용자 정의 명령
Nightwatch는 키 입력, 마우스 클릭 및 기타 입력을 시뮬레이트 할 수있는 사용자 정의 명령 작성을 지원합니다. 커스텀 커맨드는 다른 Nightwatch 커맨드와 연결될 수 있습니다 :
module.exports = {
"Login App" : function (client) {
client
.url("http://localhost:3000")
.login("[email protected]", "janedoe123")
.end();
}
};
이 기능을 사용하려면 ./tests/nightwatch/commands/login
에서 ./tests/nightwatch/commands/login
과 같이 명령을 정의하십시오.
exports.command = function(username, password) {
this
.verify.elementPresent('#login')
// we clear the input in case there's any data remaining from previous visits
.clearValue("#emailInput")
.clearValue("#passwordInput")
// we simulate key presses
.setValue("#emailInput", username)
.setValue("#passwordInput", password)
// and we simulate a mouse click
.click("#signInToAppButton").pause(1000)
return this; // allows the command to be chained.
};
이 모든 작업을 수행하려면 로그인 페이지에 id
속성을 추가해야합니다. 어떤 수준에서는 대략 다음과 같이 보일 것입니다.
<template name="login">
<div id="login">
<input id="emailInput" name="email" type="email" />
<input id="passwordInput" name="password" type="password" />
<button id="#signInToAppButton">Sign In</button>
</div>
</template>
클라이언트에서 유성 객체 검사하기
Nightwatch는 브라우저 콘솔에 액세스 할 수 있기 때문에 .execute()
API를 사용하여 클라이언트 측 객체를 검사 할 수 있습니다. 다음 예제에서는 Session 객체에서 특정 세션 변수를 확인합니다. 먼저 우리는 ./tests/nightwatch/api/meteor/checkSession
파일을 생성합니다. 여기서 다음 명령을 사용합니다 :
// syncrhonous version; only works for checking javascript objects on client
exports.command = function(sessionVarName, expectedValue) {
var client = this;
this
.execute(function(data){
return Session.get(data);
}, [sessionVarName], function(result){
client.assert.ok(result.value);
if(expectedValue){
client.assert.equal(result.value, expectedValue);
}
})
return this;
};
그러면 다음과 같이 연결할 수 있습니다.
module.exports = {
"Check Client Session" : function (client) {
client
.url("http://localhost:3000")
.checkSession("currentUser", "Jane Doe")
.end();
}
};
양식 및 입력 유형
파일을 업로드하려면 먼저 / data 디렉토리를 만들고 업로드 할 파일을 추가해야합니다.
tests/nightwatch/data/IM-0001-1001.dcm
양식에 파일 형식의 입력이 필요합니다. (어떤 사람들은이 입력이 제공하는 스타일 옵션이 마음에 들지 않으며 일반적인 패턴은이 입력을 숨기고 페이지의 다른 버튼을 사용자를 대신하여 클릭하는 것입니다.)
<form id="myform">
<input type="file" id="fileUpload">
<input type="text" name="first_name">
<input type="text" name="last_name">
<input type="date" name="dob_month">
<input type="date" name="dob_day">
<input type="date" name="dob_year">
<input type="radio" name="gender" value="M">
<input type="radio" name="gender" value="F">
<input type="radio" name="gender" value="O">
<input type="select" name="hs_graduation_year">
<input type="text" name="city">
<input type="select" name="state">
<input type="submit" name="submit" value="Submit">
</form>
그러면 테스트에서 setValue ()를 사용하여 로컬 파일 자산의 경로를 확인해야합니다.
module.exports = {
"Upload Study" : function (client) {
console.log(require('path').resolve(__dirname + '/../data' ));
var stringArray = "Chicago";
client
.url(client.globals.url)
.verify.elementPresent("form#myform")
// input[type="file"]
.verify.elementPresent("input#fileUpload")
.setValue('input#fileUpload', require('path').resolve(__dirname + '/../data/IM-0001-1001.dcm'))
// input[type="text"]
.setValue('input[name="first_name"]', 'First')
.setValue('input[name="last_name"]', 'Last')
// input[type="date"]
.click('select[name="dob_month"] option[value="3"]')
.click('select[name="dob_day"] option[value="18"]')
.click('select[name="dob_year"] option[value="1987"]')
// input[type="radio"]
.click('input[name="gender"][value="M"]')
// input[type="number"]
.click('select[name="hs_graduation_year"] option[value="2002"]')
// input[type="text"]
// sometimes Nightwatch will send text faster than the browser can handle
// which will cause skipping of letters. In such cases, we need to slow
// Nightwatch down; which we do by splitting our input into an array
// and adding short 50ms pauses between each letter
for(var i=0; i < userIdArray.length; i++) {
client.setValue('input[name="city"]', stringArray[i]).pause(50)
}
// input[type="select"]
// after an array input above, we need to resume our method chain...
client.click('select[name="state"] option[value="CA"]')
// input[type="number"]
.setValue('input[name="zip"]', '01234')
//input [ type="submit" ]
.click('button[type="submit"]')
.end();
}
};
Daniel Rinehart 가이 예제를 흉내 내고 있습니다.
구성 요소 및 페이지 개체
페이지 객체는 사용자 정의 명령과 유사합니다. 특정 UI 구성 요소와 연관된 사용자 지정 명령 모음입니다. 이는 React와 같은 현대적인 구성 요소 기반 설계에서 매우 잘 작동합니다.
module.exports = {
url: 'http://localhost:3000/login',
commands: [{
login: function(email, password) {
return this
.clearValue('input[name="emailAddress"]')
.clearValue('input[name="password"]')
.setValue('input[name="emailAddress"]', email)
.setValue('input[name="password"]', password)
.verify.elementPresent('#loginButton')
.click("#loginButton");
},
clear: function() {
return this
.waitForElementVisible('@emailInput')
.clearValue('@emailInput')
.clearValue('@passInput')
.waitForElementVisible('@loginButton')
.click('@loginButton')
},
checkElementsRendered: function(){
return this
.verify.elementPresent("#loginPage")
.verify.elementPresent('input[name="emailAddress"]')
.verify.elementPresent('input[name="password"]')
},
pause: function(time, client) {
client.pause(time);
return this;
},
saveScreenshot: function(path, client){
client.saveScreenshot(path);
return this;
}
}],
elements: {
emailInput: {
selector: 'input[name=email]'
},
passInput: {
selector: 'input[name=password]'
},
loginButton: {
selector: 'button[type=submit]'
}
}
};
테스트 컴포넌트에서 PageObject 패턴을 사용하는 유일한주의 사항은 네이티브 Nightwatch verify.elementPresent
제공하는 메소드 체인 플로우를 verify.elementPresent
입니다. 대신 페이지 객체를 변수에 할당하고 각 페이지에 대해 새 메서드 체인을 인스턴스화해야합니다. 코드 재사용을 테스트하기위한 일관되고 안정적인 패턴을 지불하는 합리적인 가격.
module.exports = {
tags: ['accounts', 'passwords', 'users', 'entry'],
'User can sign up.': function (client) {
const signupPage = client.page.signupPage();
const indexPage = client.page.indexPage();
client.page.signupPage()
.navigate()
.checkElementsRendered()
.signup('Alice', 'Doe', '[email protected]', 'alicedoe')
.pause(1500, client);
indexPage.expect.element('#indexPage').to.be.present;
indexPage.expect.element('#authenticatedUsername').text.to.contain('Alice Doe');
},
}