๐ ํ์ฌ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ
VSCode/
โโโ JavaScript_Prac/
โ โโโ LoginPage.js
โ โโโ LoginPage.test.js
โโโ package.json
โฌ๏ธ LoginPage.js
const { By } = require('selenium-webdriver');
class LoginPage {
constructor(driver) {
this.driver = driver;
this.emailInput = By.id("email");
this.pwdInput = By.id("password");
};
async getElement(el) {
return await this.driver.findElement(el);
}
async getInputValue(locator) {
const element = await this.driver.findElement(locator);
return await element.getAttribute("value");
}
async sendTxt(el, txt) {
await this.driver.findElement(el).sendKeys(txt);
}
async clickBtn(el) {
await this.driver.findElement(el).click();
}
}
module.exports = LoginPage;
โฌ๏ธ LoginPage.test.js
const { Builder } = require("selenium-webdriver");
const LoginPage = require('./LoginPage.js');
const BASE_URL = "http://localhost:3000/login";
const TIMEOUT = 10000;
describe("๋ฉ์ธ ํ์ด์ง ๊ฐ์ฒด ๋ชจ๋ธ ํ
์คํธ", () => {
let driver;
let loginPage;
beforeEach(async () => {
driver = await new Builder().forBrowser("chrome").build();
loginPage = new LoginPage(driver);
await driver.get(BASE_URL);
}, TIMEOUT);
afterEach(async () => {
if (driver) {
await driver.quit();
}
});
it("๋ก๊ทธ์ธ ํ
์คํธ", async () => {
const emailValue = "asdf@naver.com";
const pwdValue = "asdf1234";
await loginPage.sendTxt(loginPage.emailInput, emailValue);
await loginPage.sendTxt(loginPage.pwdInput, pwdValue);
const actualEmailValue = await loginPage.getInputValue(loginPage.emailInput);
const actualPwdValue = await loginPage.getInputValue(loginPage.pwdInput);
expect(actualEmailValue).toBe(emailValue);
expect(actualPwdValue).toBe(pwdValue);
});
});
โฌ๏ธ package.json
{
"dependencies": {
"jest": "^29.7.0",
"selenium-webdriver": "^4.31.0"
},
"scripts": {
"test": "jest"
}
}
JavaScript์ Jest์ ์ ์ํ๊ณ ์ ๊ฐ๋จํ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํด๋ดค๋ค. ์๋ ๋จ์ํ ๊ตฌ์กฐ๋ผ ๋ฌธ์ ์์ด ์ ์๋ํ๊ธด ํ์ง๋ง, ์ฝ๋๋ฅผ ๋ค์ฌ๋ค๋ณด๋ ๊ธ์ธ ๊ฐ์ ํด์ผ ํ ๋ถ๋ถ๋ค์ด ๋์ ๋์๋ค.
๐ฅ ๋ฌธ์ ์ 1
์ฒซ ๋ฒ์งธ ๋ฌธ์ ๋ LoginPage ํด๋์ค์ ์์ฑ์ ๋ด๋ถ์ locator๋ฅผ ์ง์ ์ ์ํ ๊ฒ์ด๋ค. ์ฒ์์ ๊ฐ๋จํ๊ฒ ๋ณด์ด์ง๋ง, ์๊ฐ์ด ์ง๋ ์๋ก ์ ์ง๋ณด์๊ฐ ์ ์ ์ด๋ ค์์ง๋ค. ์๋ฅผ ๋ค์ด, ํ์ด์ง ๊ตฌ์กฐ๊ฐ ๋ณ๊ฒฝ๋์ด ๋ก๊ทธ์ธ ๋ฒํผ์ ID๊ฐ loginBtn์์ submitBtn์ผ๋ก ๋ฐ๋์๋ค๊ณ ๊ฐ์ ํด๋ณด์. locator๊ฐ ํด๋์ค ๋ด๋ถ์ ์ ์๋์ด ์๋ค๋ฉด, ์ด ํ์ผ์ ์ด์ด ์ง์ ์์ ํด์ผ ํ๋ค. ๋จ์ํ ์์ ๋ง ํ๋ฉด ๋์ง ์๋๋๊ณ ์๊ฐํ ์ ์์ง๋ง, ํ์ด์ง๊ฐ ๋ง์์ง๊ณ ๊ณตํต ์์๋ค์ด ์ฌ๋ฌ ๊ณณ์ ์ค๋ณต๋๊ธฐ ์์ํ๋ฉด ์ํฉ์ด ๋ฌ๋ผ์ง๋ค. ๊ฐ์ ์์๋ฅผ ์ฌ๋ฌ ํด๋์ค์์ ์ค๋ณต ์ ์ํ๊ณ ์์๋ค๋ฉด, ๊ทธ๊ฑธ ๋ชจ๋ ์ฐพ์๊ฐ๋ฉฐ ์์ ํด์ผ ํ๋ ์ํฉ์ด ๋ฐ์ํ๋ค. ๊ฒฐ๊ตญ ๋ณ๊ฒฝ์ ์ ์ฐํ์ง ๋ชปํ ๊ตฌ์กฐ๊ฐ ๋๊ณ , ์์ UI ๋ณ๊ฒฝ์๋ ์ฝ๋ ์ ์ฒด๋ฅผ ๋ค์ค์ ์ผ ํ๋ ๋นํจ์จ์ด ์๊ธฐ๋ ๊ฒ์ด๋ค.
๐ฅ ๋ฌธ์ ์ 2
๋ ๋ฒ์งธ ๋ฌธ์ ๋ ํ ์คํธ ๋ฐ์ดํฐ์ ํ๋์ฝ๋ฉ์ด๋ค. LoginPage.test.js ํ์ผ ์์ ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ ๊ฐ์ ์ง์ ๋ฃ์ด๋๋ ๋ฐฉ์์ ๋ฑ 1๊ฐ์ ๊ฒฝ์ฐ๋ง ํ ์คํธํ ์ ์์ ๋ฟ์ด๋ฉฐ, ๋ค๋ฅธ ์ผ์ด์ค๋ฅผ ์ถ๊ฐํ๋ ค๋ฉด ํ ์คํธ ์ฝ๋๋ฅผ ๋ฐ๋ณต ์์ฑํด์ผ ํ๋ค. ํ ์คํธ ์ผ์ด์ค๊ฐ ๋ง์์ง์๋ก ์ค๋ณต๋ ์ฆ๊ฐํ๊ณ , ๊ด๋ฆฌ๊ฐ ๋ฒ๊ฑฐ๋ก์์ง๋ค.
๐ก ํด๊ฒฐ์ฑ
๊ทธ๋ ๋ค๋ฉด ์ด ๋ฌธ์ ๋ค์ ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์์๊น? ํด๋ต์ ๋ฐ๋ก ๋ชจ๋ํ๋ค.
๐ ๋ณ๊ฒฝ๋ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ
VSCode/
โโโ JavaScript_Prac/
โ โโโ pages/
โ โ โโโ LoginPage.js
โ โ โโโ LoginPage.locator.js
โ โโโ tests/
โ โ โโโ LoginPage.test.js
โ โ โโโ data/
โ โ โโโ loginData.js
โ โโโ package.json
์ฌ์ค ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ ๋ณธ์ธ์ ์ทจํฅ์ ๋ฐ๋ผ ์์ ๋กญ๊ฒ ๊ตฌ์ฑํ๋ฉด ๋๋ค. ๋ง์ฝ ํ์ฌ์์ ์ ๊ณตํ๋ ๊ณต์ ๊ตฌ์กฐ๊ฐ ์๋ค๋ฉด ๊ฑฐ๊ธฐ์ ๋ง์ถ๋ฉด ๋๋ ๊ฒ์ด๊ณ , ๊ฐ์ธ ํ๋ก์ ํธ๋ผ๋ฉด ๋ณธ์ธ์ด ๊ด๋ฆฌํ๊ธฐ ํธํ ๋ฐฉ์์ผ๋ก ์ค์ ํ๋ฉด ๋๋ค. ์ด๋ฒ์๋ ๊ฐ๋จํ ํ ์คํธ๋ฅผ ์งํํด๋ณธ ๊ฑฐ๋ผ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ ์์๋ก ๊ตฌ์ฑํ์ง๋ง, ํ์ด์ง ์๊ฐ ๋ง์์ง๋ค๋ฉด locators ํด๋๋ฅผ ๋ฐ๋ก ๋ง๋ค์ด ๊ด๋ฆฌํ๋ ๊ฒ์ด ํจ์ฌ ์ข์ ๊ฒ ๊ฐ๋ค.
โฌ๏ธ LoginPage.js
class LoginPage {
constructor(driver) {
this.driver = driver;
}
async getElement(locator) {
return await this.driver.findElement(locator);
}
async getInputValue(locator) {
const element = await this.driver.findElement(locator);
return await element.getAttribute("value");
}
async sendTxt(locator, txt) {
await this.driver.findElement(locator).sendKeys(txt);
}
async clickBtn(locator) {
await this.driver.findElement(locator).click();
}
}
module.exports = LoginPage;
โฌ๏ธ LoginPage.test.js
const { Builder } = require("selenium-webdriver");
const LoginPage = require("../pages/LoginPage.js");
const Locator = require("../pages/LoginPage.locator.js");
const loginData = require("./data/loginData.js");
const BASE_URL = "http://localhost:3000/login";
const TIMEOUT = 10000;
describe("๋ก๊ทธ์ธ ํ
์คํธ (๋ฐ์ดํฐ ๊ธฐ๋ฐ)", () => {
let driver;
let loginPage;
beforeEach(async () => {
driver = await new Builder().forBrowser("chrome").build();
loginPage = new LoginPage(driver);
await driver.get(BASE_URL);
}, TIMEOUT);
afterEach(async () => {
if (driver) {
await driver.quit();
}
});
test.each(loginData)("๋ก๊ทธ์ธ ์ ์
๋ ฅ๊ฐ ํ์ธ: ๋ฐ์ดํฐ (%s)", async ({ email, password }) => {
await loginPage.sendTxt(Locator.emailInput, email);
await loginPage.sendTxt(Locator.pwdInput, password);
const actualEmail = await loginPage.getInputValue(Locator.emailInput);
const actualPwd = await loginPage.getInputValue(Locator.pwdInput);
expect(actualEmail).toBe(email);
expect(actualPwd).toBe(password);
});
});
โฌ๏ธ LoginPage.locator.js
const { By } = require('selenium-webdriver');
const LoginPageLocator = {
emailInput: By.id("email"),
pwdInput: By.id("password")
};
module.exports = LoginPageLocator;
โฌ๏ธ loginData.js
module.exports = [
{ email: "asdf@naver.com", password: "asdf1234" },
{ email: "test@example.com", password: "pass1234" },
{ email: "hello@world.com", password: "securepass" }
];
loginData.js์ ์ด 3๊ฐ์ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ์ ์ํ๊ธฐ ๋๋ฌธ์, test.each()๋ฅผ ํตํด ๊ฐ ๋ฐ์ดํฐ์ ๋ํด ํ ์คํธ๊ฐ ํ ๋ฒ์ฉ ์คํ๋๋ค. ๊ทธ ๊ฒฐ๊ณผ Tests: 3 passed๋ก ํ์๋๋ค. ํ์ง๋ง ์ค์ ๋ก๋ ์ด ๋ชจ๋ ํ ์คํธ๊ฐ ํ๋์ ํ ์คํธ ํ์ผ(LoginPage.test.js) ๋ด์์ ์ํ๋๊ธฐ ๋๋ฌธ์ Test Suites: 1 passed๋ก ์ถ๋ ฅ๋๋ ๊ฒ์ด๋ค.
๐ ๋ฆฌํฉํ ๋ง์ ํตํด ์ป์ ๊ตํ
์ด์ฒ๋ผ ํจ์จ์ ์ด๊ณ ํ์ฅ ๊ฐ๋ฅํ ์๋ํ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํด์๋, ๊ธฐ๋ฅ๊ณผ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ํํ๊ณ , ๊ตฌ์กฐํ๋ ํจํด(POM ๋ฑ)์ ๋ฐํ์ผ๋ก ํ ์คํธ ์ค๊ณ๋ฅผ ์ฒด๊ณํํ๋ ๊ฒ์ด ์ค์ํ๋ค. ์์ ๋ฆฌํฉํ ๋ง์์ ์์ํ๋๋ผ๋, ๊ทธ ๊ฒฝํ์ ์ค์ ์๋น์ค์ ํ์ง๊ณผ ์ ์ง๋ณด์ ํจ์จ์ ๋์ด๋ ๋ฐ ํฐ ๋์์ด ๋๋ค.
'๐ Quality Assurance Study > ๐ QA ๊ณต๋ถ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Unity์์์ ํ ์คํธ ์๋ํ ๋ฐ Jira ์ด์ ๋ฑ๋ก ์๋ํ (0) | 2025.03.09 |
---|---|
Jira REST API ํ ํฐ ๋ฐ๊ธ ๋ฐ ์ด์ ์กฐํ (0) | 2025.03.02 |
XPath์ ๋ํ์ฌ (0) | 2025.02.27 |
Jira ๋ฐ Confluence ์ฌ์ฉ ๋ฐฉ๋ฒ (2) | 2025.02.20 |
BTS (Bug Tracking System)์ ๋ํ์ฌ (3) | 2025.01.13 |