크롬 확장을 테스트하는 방법은?
이것을 할 수 있는 좋은 방법이 있습니까?웹사이트와 콘텐츠 스크립트로 상호작용하여 로컬 스토리지로 데이터를 저장하는 확장자를 작성합니다.이 행동을 테스트하기 위해 사용할 수 있는 도구, 프레임워크 등이 있습니까?자바스크립트를 테스트하기 위한 일반적인 도구들이 있다는 것을 알고 있지만, 확장자를 테스트하기에 충분한 능력이 있습니까?유닛 테스트도 중요하지만, 다른 테스트(통합 테스트 등)에도 관심이 있습니다.
네, 기존 프레임워크는 꽤 유용합니다.
최근에 저는 모든 테스트를 응용 프로그램에 내장되어 있지만 물리적으로 입력하지 않으면 연결할 수 없는 "테스트" 페이지에 배치했습니다.
예를 들어, 나는 아래에서 접근할 수 있는 페이지의 모든 테스트를 가질 것입니다.chrome-extension://asdasdasdasdad/unittests.html
테스트를 통해 다음 단계별로localStorage
등의 방법으로 컨텐츠 스크립트에 액세스할 경우, 이론적으로는 테스트 페이지에 내장된 IFRAME을 통해 테스트할 수 있지만, 이는 더 많은 통합 수준의 테스트이므로 단위 테스트에서는 실제 페이지에서 해당 IFRAME을 추상화하여 사용자가 의존하지 않도록 해야 합니다. localStorage에 대한 액세스도 마찬가지입니다.
페이지를 직접 테스트하려면 확장을 조정하여 새 탭(chrome.tab.create({"url" : "somurl"})을 열 수 있습니다.각 새 탭에 대해 컨텐츠 스크립트가 실행되어야 하며 테스트 프레임워크를 사용하여 코드가 수행해야 할 작업을 수행했는지 확인할 수 있습니다.
프레임워크에 관해서는 JsUnit이나 최신 Jasmine이 잘 작동할 것입니다.
몇 가지 크롬 확장을 작업하면서 다음을 사용하여 단위 테스트를 실행할 수 있는 프로젝트를 생각해 냈습니다.mocha
,nodejs
그리고.phantomjs
.
기본적으로, 그것은 모두의 사이논 모조품을 만들어냅니다.chrome.*
미리 정의된 js를 응답에 넣을 수 있는 API.
다음으로 노드의 스크립트를 사용하여 스크립트를 로드합니다.vm.runInNewContext
배경 페이지 및phantomjs
렌더 팝업 / 옵션 페이지를 입력합니다.
그리고 마지막으로 당신은 크롬 API가 필요한 인수를 가지고 호출되었다고 주장합니다.
예를 들어 보겠습니다.
버튼 배지에 열려 있는 탭 수를 표시하는 단순한 크롬 확장 기능이 있다고 가정합니다.
배경 페이지:
chrome.tabs.query({}, function(tabs) {
chrome.browserAction.setBadgeText({text: String(tabs.length)});
});
테스트하려면 다음이 필요합니다.
- 모의의
chrome.tabs.query
미리 정의된 응답(예: 탭 2개)을 반환합니다. - 조롱당한 자들에게 주사를 놓다
chrome.*
일부 환경에 api. - 이 환경에서 확장 코드를 실행합니다.
- 버튼 배지가 '2'와 같다고 주장합니다.
코드 조각은 다음과 같습니다.
const vm = require('vm');
const fs = require('fs');
const chrome = require('sinon-chrome');
// 1. mock `chrome.tabs.query` to return predefined response
chrome.tabs.query.yields([
{id: 1, title: 'Tab 1'},
{id: 2, title: 'Tab 2'}
]);
// 2. inject our mocked chrome.* api into some environment
const context = {
chrome: chrome
};
// 3. run our extension code in this environment
const code = fs.readFileSync('src/background.js');
vm.runInNewContext(code, context);
// 4. assert that button badge equals to '2'
sinon.assert.calledOnce(chrome.browserAction.setBadgeText);
sinon.assert.calledWithMatch(chrome.browserAction.setBadgeText, {
text: "2"
});
이제 모카로 포장할 수 있습니다.describe..it
기능 및 터미널에서 실행:
$ mocha
background page
✓ should display opened tabs count in button badge
1 passing (98ms)
여기서 전체적인 예를 찾을 수 있습니다.
또한 사이논 크롬은 미리 정의된 응답으로 크롬 이벤트를 유발할 수 있습니다.
chrome.tab.onCreated.trigger({url: 'http://google.com'});
하는 동안에sinon.js
잘 작동하는 것 같습니다. 그냥 평범한 재스민을 사용하고 필요한 크롬 콜백을 조롱할 수도 있습니다.예:
chrome = {
runtime: {
onMessage : {
addListener : function() {}
}
}
}
describe("JSGuardian", function() {
describe("BlockCache", function() {
beforeEach(function() {
this.blockCache = new BlockCache();
});
it("should recognize added urls", function() {
this.blockCache.add("http://some.url");
expect(this.blockCache.allow("http://some.url")).toBe(false);
});
} // ... etc
기본값만 수정하면 코드가 실행됩니다.
Chrome에 이미 존재하는 툴 정보:
크롬 개발자 도구에는 Resources For local storage 섹션이 있습니다.
개발자 도구 > 리소스 > 로컬 스토리지
로컬 스토리지의 변화를 확인할 수 있습니다.
console.profile을 사용하여 성능을 테스트하고 런타임 호출 스택을 확인할 수 있습니다.
- fileSystem 이 URL을 사용하여 파일이 업로드되었는지 여부를 확인할 수 있습니다. filesystem:chrome-extension://temporary/
배경 페이지/스크립트 없이, 메시지 전달 없이 컨텐츠 스크립트와 로컬 스토리지를 함께 사용하는 경우, 해당 사이트에서만 로컬 스토리지에 액세스할 수 있습니다.따라서 해당 페이지를 테스트하려면 해당 탭에 테스트 스크립트를 주입해야 합니다.
End-to-End를 테스트하려면 다음을 사용할 수 있습니다.puppeteer
. 로드된 내선번호를 확인하기 위해 내선번호를 위해 작성한 부분입니다.title
인코그니토 모드에서 확장이 활성화되었는지 확인합니다.
const path = require("path");
const puppeteer = require("puppeteer");
const assert = require("assert");
const Constants = require("../contants");
const Utils = require("./util");
const extensionID = Constants.EXTENSION_ID;
const extensionPath = path.join(__dirname, "../dist");
const extensionOptionHtml = "option.html";
const extPage = `chrome-extension://${extensionID}/${extensionOptionHtml}`;
let extensionPage = null;
let browser = null;
async function boot() {
browser = await puppeteer.launch({
// slowMo: 250,
headless: false, // extension are allowed only in head-full mode
args: [
`--disable-extensions-except=${extensionPath}`,
`--load-extension=${extensionPath}`,
"--no-sandbox",
"--disable-setuid-sandbox"
]
});
extensionPage = await browser.newPage();
await extensionPage.goto(extPage);
}
describe("Extension UI Testing", function() {
this.timeout(20000); // default is 2 seconds and that may not be enough to boot browsers and pages.
before(async function() {
await boot();
});
describe("option page home", async function() {
it("check title", async function() {
const h1 = "Allow extension in Incognito Mode";
const extH1 = await extensionPage.evaluate(() =>
document.querySelector("h1").textContent.trim()
);
assert.equal(extH1, h1);
});
it("show option ui after enabling extension in incognito", async () => {
await extensionPage.goto(`chrome://extensions/?id=${extensionID}`);
extensionPage.evaluate(() =>
document
.querySelector("body > extensions-manager")
.shadowRoot.querySelector("#viewManager > extensions-detail-view")
.shadowRoot.querySelector("#allow-incognito")
.shadowRoot.querySelector("#crToggle")
.click()
);
await Utils.sleep(2000);
await extensionPage.goto(
`chrome-extension://${extensionID}/${extensionOptionHtml}`
);
const h3 = "Mark Incognito";
const headingID = `#${Constants.OPTION_SCRIPT_HOST_ID} > div > div > header > div > h6`;
await extensionPage.waitFor(headingID);
console.log({ headingID });
const extH3 = await extensionPage.evaluate(headingID => {
return document.querySelector(headingID).textContent.trim();
}, headingID);
console.log({ extH3 });
assert.equal(extH3, h3);
});
});
after(async function() {
await browser.close();
});
});
저는 셀레늄 웹 드라이버를 사용하여 확장자가 미리 설치된 새 브라우저 인스턴스를 시작하고 클릭 시에는 pyautogui를 사용할 수 있음을 알게 되었습니다. - 셀레늄은 확장자의 "보기"를 구동할 수 없기 때문입니다.클릭 후 스크린샷을 만들어 '예상' 스크린샷과 비교할 수 있으며 95%의 유사성을 기대할 수 있습니다(다른 브라우저에서는 몇 픽셀로 마크업 이동이 허용되므로).
몇 가지 이전 답변을 확인해 드리자면, 재스민은 크롬 확장 기능과 잘 작동하는 것 같습니다.버전 3.4.0을 사용하고 있습니다.
Jasmine 스파이를 사용하여 다양한 API에 대한 테스트 더블을 쉽게 만들 수 있습니다.처음부터 자신만의 것을 구축할 필요가 없습니다.예를 들어,
describe("Test suite", function() {
it("Test case", function() {
// Set up spies and fake data.
spyOn(chrome.browserAction, "setPopup");
spyOn(chrome.identity, "removeCachedAuthToken");
fakeToken = "faketoken-faketoken-faketoken";
fakeWindow = jasmine.createSpyObj("window", ["close"]);
// Call the function under test.
logout(fakeWindow, fakeToken);
// Perform assertions.
expect(chrome.browserAction.setPopup).toHaveBeenCalledWith({popup: ""});
expect(chrome.identity.removeCachedAuthToken).toHaveBeenCalledWith({token: fakeToken});
expect(fakeWindow.close.calls.count()).toEqual(1);
});
});
도움이 되는 경우 추가 정보:
다른 답변에서 언급했듯이, 저는 테스트를 실행하는 브라우저 확장의 일부로 HTML 페이지를 만들었습니다.HTML 페이지에는 재스민 라이브러리와 내 확장자의 자바스크립트 코드, 그리고 내 테스트 스위트가 포함되어 있습니다.테스트는 자동으로 실행되고 결과는 사용자에게 맞게 포맷됩니다.테스트 러너나 결과를 작성할 필요가 없습니다.설치 지침을 따르고, 거기에 문서화된 HTML을 사용하여 테스트 런너 페이지를 만들고, 테스트 스위트도 페이지에 포함시키기만 하면 됩니다.
다른 호스트에서 동적으로 Jasmine 프레임워크를 가져올 수 없을 것 같아서 제 확장에 Jasmine 릴리즈를 포함시켰습니다.물론 생산을 위한 확장 공사를 할 때 그것과 테스트 케이스도 생략할 것입니다.
명령 줄에서 테스트를 실행하는 방법을 살펴보지 않았습니다.자동화된 배포 도구에 도움이 될 것입니다.
언급URL : https://stackoverflow.com/questions/2869827/how-to-test-chrome-extensions
'source' 카테고리의 다른 글
Mysql vs Oracle XE vs Postgresql. 확장성 및 성능, 어떤 것을 선택해야 합니까? (0) | 2023.10.29 |
---|---|
왜 strdup이 사악하다고 여겨지나요? (0) | 2023.10.29 |
모든 경로에서 Can Activate guard를 신청하는 방법은? (0) | 2023.10.29 |
C와 C++ 컴파일러가 명시적으로 초기화된 글로벌 변수와 기본 초기화된 글로벌 변수를 서로 다른 세그먼트에 배치하는 이유는 무엇입니까? (0) | 2023.10.29 |
앱이 다시 시작되지 않고 다시 시작됨 (0) | 2023.10.29 |