วิธีทดสอบส่วนขยายของโครเมี่ยม


154

มีวิธีที่ดีในการทำเช่นนี้? ฉันกำลังเขียนส่วนขยายที่โต้ตอบกับเว็บไซต์เป็นสคริปต์เนื้อหาและบันทึกข้อมูลโดยใช้การจัดเก็บในพื้นที่ มีเครื่องมือกรอบงาน ฯลฯ ที่ฉันสามารถใช้ทดสอบพฤติกรรมนี้ได้หรือไม่ ฉันรู้ว่ามีเครื่องมือทั่วไปสำหรับทดสอบ Javascript แต่มีพลังเพียงพอที่จะทดสอบส่วนขยายหรือไม่ การทดสอบหน่วยเป็นสิ่งที่สำคัญที่สุด แต่ฉันก็สนใจการทดสอบประเภทอื่น (เช่นการทดสอบการรวม)


8
ฉันเพิ่งเขียนคำตอบที่ยอมรับซึ่งการทดสอบหน่วยและการทดสอบการรวมสำหรับส่วนขยายเบราว์เซอร์ในทุกเบราว์เซอร์ไม่ใช่แค่ Chrome ดูคำตอบที่ "การทดสอบส่วนขยายเบราว์เซอร์ที่"
Rob W

คำตอบ:


111

ใช่กรอบงานที่มีอยู่ค่อนข้างมีประโยชน์ ..

ในอดีตที่ผ่านมาฉันได้วางการทดสอบทั้งหมดของฉันในหน้า "การทดสอบ" ที่ฝังอยู่ในแอปพลิเคชัน แต่ไม่สามารถเข้าถึงได้เว้นแต่จะพิมพ์ทางกายภาพ

ตัวอย่างเช่นฉันจะมีการทดสอบทั้งหมดในหน้าสามารถเข้าถึงได้ภายใต้ chrome-extension://asdasdasdasdad/unittests.html

การทดสอบจะมีการเข้าถึงlocalStorageเป็นต้นสำหรับการเข้าถึงสคริปต์เนื้อหาในทางทฤษฎีคุณสามารถทดสอบได้ว่าผ่าน IFRAME แบบฝังในหน้าทดสอบของคุณอย่างไรก็ตามการทดสอบเหล่านี้เป็นการทดสอบในระดับการรวมกลุ่มที่มากขึ้นการทดสอบหน่วยจะทำให้คุณแยกจากหน้าจริง ๆ ไม่ขึ้นอยู่กับพวกเขาเช่นเดียวกันกับการเข้าถึง localStorage

หากคุณต้องการทดสอบหน้าโดยตรงคุณสามารถดัดแปลงส่วนขยายเพื่อเปิดแท็บใหม่ (chrome.tab.create ({"url": "someurl"})) สำหรับแต่ละแท็บใหม่สคริปต์เนื้อหาของคุณควรจะทำงานและคุณสามารถใช้ กรอบการทดสอบของคุณเพื่อตรวจสอบว่ารหัสของคุณทำในสิ่งที่ควรทำ

สำหรับเฟรมเวิร์กJsUnitหรือจัสมินที่ใหม่กว่าน่าจะทำงานได้ดี


1
คุณถูกต้องการทดสอบหน้าจริงไม่ได้อยู่ภายใต้การทดสอบหน่วย ฉันควรทำให้คำถามของฉันกว้างขึ้น แต่มันก็ยังเป็นสิ่งที่ฉันต้องการทดสอบโดยเฉพาะอย่างยิ่งเนื่องจากโครงสร้าง html เว็บไซต์สามารถเปลี่ยนแปลงได้ตลอดเวลา ฉันแก้ไขคำถามแล้ว
swampsjohn

1
ฉันจะทดสอบผ่าน IFrames ในหน้าทดสอบหน่วยของคุณ สคริปต์เนื้อหาจะยังคงไฟ (ถ้าคุณเปิดใช้งานสคริปต์ในการทำงานใน iFrame) ที่
Kinlan

3
ส่วนขยายตัวอย่างพร็อกซีมีการทดสอบบางอย่างซึ่งเพิ่งลอกเลียนแบบบิตและส่วนต่างๆของ Chrome API ที่จำเป็น: code.google.com/chrome/extensions/samples.html#chrome.proxy .. นอกจากนี้ Boris เพื่อนร่วมงานของเรายังใช้ QUnit สำหรับการทดสอบ เลเยอร์ "โมเดล" ของเขา: github.com/borismus/Question-Monitor-for-Stack-Exchange/tree/…
พอลไอริช

63

การทำงานในส่วนขยายโครเมี่ยมหลายฉันมากับsinon-chromeโครงการที่จะช่วยให้การเรียกใช้การทดสอบหน่วยใช้mocha, และnodejsphantomjs

โดยพื้นฐานแล้วมันสร้าง sinon mocks ของchrome.*API ทั้งหมดที่คุณสามารถใส่คำตอบ json ที่กำหนดไว้ล่วงหน้า

ถัดไปคุณโหลดสคริปต์โดยใช้โหนดvm.runInNewContextสำหรับหน้าพื้นหลังและphantomjsสำหรับการแสดงผลหน้าป๊อปอัพ / ตัวเลือก

และในที่สุดคุณยืนยันว่า Chrome API ถูกเรียกใช้พร้อมกับอาร์กิวเมนต์ที่จำเป็น

ลองมาตัวอย่าง:
สมมติว่าเรามีส่วนขยายโครเมี่ยมอย่างง่ายที่แสดงจำนวนแท็บที่เปิดในป้ายปุ่ม

หน้าพื้นหลัง:

chrome.tabs.query({}, function(tabs) {
  chrome.browserAction.setBadgeText({text: String(tabs.length)});
});

เพื่อทดสอบเราต้องการ:

  1. จำลองchrome.tabs.queryเพื่อกลับคำตอบที่กำหนดไว้ล่วงหน้าเช่นสองแท็บ
  2. ฉีดchrome.*API ที่เยาะเย้ยของเราในสภาพแวดล้อมบางอย่าง
  3. เรียกใช้รหัสส่วนขยายของเราในสภาพแวดล้อมนี้
  4. ยืนยันว่าปุ่มตราเท่ากับ '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)

คุณสามารถหาตัวอย่างเต็มรูปแบบที่นี่

นอกจากนี้ sinon-chrome ช่วยให้สามารถเรียกใช้เหตุการณ์ chrome ใด ๆ ที่มีการตอบสนองที่กำหนดไว้ล่วงหน้าเช่น

chrome.tab.onCreated.trigger({url: 'http://google.com'});

ลิงค์สำหรับตัวอย่างดูเหมือนจะตาย - คุณช่วยอัพเดทได้ไหม
Raisen

1
อัปเดตลิงก์ไปยังตัวอย่างแล้ว นอกจากนี้ sinon-chrome ก็ถูกย้ายไปที่github.com/acvetkovและจะมีตัวอย่างใหม่ในไม่ช้า
vitalets

3

ในขณะที่sinon.jsดูเหมือนว่าจะทำงานได้ดีคุณสามารถใช้จัสมินธรรมดาและจำลองการโทรกลับ Chrome ที่คุณต้องการ ตัวอย่าง:

เยาะเย้ย

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

เพียงแก้ไขค่าเริ่มต้นSpecRunner.htmlเพื่อเรียกใช้รหัสของคุณ


2

เกี่ยวกับเครื่องมือที่มีอยู่แล้วใน Chrome:

  1. ในเครื่องมือนักพัฒนาซอฟต์แวร์ Chrome มีส่วนสำหรับทรัพยากรสำหรับการจัดเก็บในตัวเครื่อง

    เครื่องมือสำหรับนักพัฒนา> แหล่งข้อมูล> ที่จัดเก็บในตัวเครื่อง

    ดูการเปลี่ยนแปลงของการจัดเก็บในพื้นที่นั้น

  2. คุณสามารถใช้ console.profile เพื่อทดสอบประสิทธิภาพและดู stack call call time

  3. สำหรับ fileSystem คุณสามารถใช้ URL นี้เพื่อตรวจสอบว่าไฟล์ของคุณเป็นแบบอัพโหลดหรือไม่: ระบบไฟล์: chrome-extension: /// ชั่วคราว /

หากคุณใช้สคริปต์เนื้อหาและที่จัดเก็บในตัวเครื่องร่วมกันโดยไม่ต้องมีหน้าพื้นหลัง / สคริปต์และไม่มีการส่งข้อความการจัดเก็บในตัวเครื่องจะสามารถเข้าถึงได้จากเว็บไซต์นั้นเท่านั้น ดังนั้นในการทดสอบหน้าเหล่านั้นคุณต้องฉีดสคริปต์ทดสอบในแท็บเหล่านั้น


1
ไม่ได้ผลสำหรับฉัน แต่มันทำให้ฉันต่อไปในจาวาสคริปต์ของฉัน +1 สำหรับสิ่งนั้น
mobibob

สำหรับระบบไฟล์คุณสามารถใช้: ระบบไฟล์: chrome-extension: // <yourextension-id> / temporary /
Nafis Ahmad

1

ฉันพบว่าฉันสามารถใช้โปรแกรมควบคุมเว็บ Seleniumเพื่อเริ่มต้นอินสแตนซ์เบราว์เซอร์ใหม่พร้อมส่วนขยายที่ติดตั้งไว้ล่วงหน้าและpyautoguiสำหรับการคลิก - เนื่องจากซีลีเนียมไม่สามารถขับ "ดู" ของส่วนขยายได้ หลังจากคลิกคุณสามารถสร้างภาพหน้าจอและเปรียบเทียบกับภาพที่คาดไว้คาดว่าจะมีความคล้ายคลึงกัน 95% (เนื่องจากในเบราว์เซอร์ที่แตกต่างกัน


0

เพื่อยืนยันคำตอบก่อนหน้านี้สองสามครั้งดูเหมือนว่าจัสมินจะทำงานได้ดีกับส่วนขยายของ Chrome ฉันใช้เวอร์ชั่น 3.4.0

คุณสามารถใช้สายลับจัสมินเพื่อสร้างคู่ทดสอบสำหรับ 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 มีไลบรารี Jasmine รวมถึงรหัส JavaScript ของส่วนขยายรวมถึงชุดทดสอบของฉัน การทดสอบจะดำเนินการโดยอัตโนมัติและผลลัพธ์จะถูกจัดรูปแบบสำหรับคุณ ไม่จำเป็นต้องสร้างนักวิ่งทดสอบหรือฟอร์แมตผลลัพธ์ เพียงทำตามคำแนะนำในการติดตั้งและใช้เอกสาร HTML ที่นั่นเพื่อสร้างหน้าทดสอบนักวิ่งของคุณและรวมชุดทดสอบไว้ในหน้าด้วย

ฉันไม่คิดว่าคุณสามารถเรียกจัสมินเฟรมเวิร์กจากโฮสต์อื่นดังนั้นฉันจึงรวมจัสมินรีลีสในส่วนขยายของฉัน ฉันจะละเว้นมันและกรณีทดสอบของฉันเมื่อสร้างส่วนขยายสำหรับการผลิตแน่นอน

ฉันไม่ได้ดูวิธีการดำเนินการทดสอบของฉันที่บรรทัดคำสั่ง นั่นจะเป็นประโยชน์สำหรับเครื่องมือการปรับใช้อัตโนมัติ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.