Advertisement
  1. Code
  2. Angular

Memulai Pengujian End-to-End di Angular Menggunakan Protractor

Scroll to top
Read Time: 18 min

() translation by (you can also view the original English article)

Final product imageFinal product imageFinal product image
What You'll Be Creating

Protractor adalah framework pengujian end-to-end yang populer yang memungkinkan Anda menguji aplikasi Angular Anda pada browser nyata yang mensimulasikan interaksi browser seperti cara pengguna nyata berinteraksi dengannya. Pengujian end-to-end dirancang untuk memastikan bahwa aplikasi berfungsi sesuai harapan dari perspektif pengguna. Selain itu, tes tidak memperhatikan implementasi kode aktual.

Protractor berjalan di atas Selenium WebDriver yang populer, yang merupakan API untuk otomatisasi dan pengujian browser. Selain fitur yang disediakan oleh Selenium WebDriver, Protractor menawarkan pencari dan metode untuk menangkap komponen UI aplikasi Angular.

Dalam tutorial ini, Anda akan belajar tentang:

  • mengatur, mengkonfigurasi dan menjalankan Protractor
  • menulis tes dasar untuk Protractor
  • objek halaman dan mengapa Anda harus menggunakannya
  • pedoman yang harus dipertimbangkan saat menulis tes
  • menulis tes E2E untuk aplikasi dari awal hingga selesai

Bukankah itu terdengar menarik? Namun, hal pertama yang pertama.

Apakah Saya Perlu Menggunakan Protractor?

Jika Anda menggunakan Angular-CLI, Anda mungkin tahu bahwa secara default, ia dikirim dengan dua framework untuk pengujian. Mereka:

  • tes unit menggunakan Jasmine dan Karma
  • tes end-to-end menggunakan Protractor

Perbedaan yang jelas antara keduanya adalah bahwa yang pertama digunakan untuk menguji logika komponen dan layanan, sedangkan yang kedua digunakan untuk memastikan bahwa fungsionalitas tingkat tinggi (yang melibatkan elemen UI) dari aplikasi berfungsi seperti yang diharapkan.

Jika Anda baru menguji di Angular, saya akan merekomendasikan membaca Komponen Pengujian dalam seri Angular Using Jasmine untuk mendapatkan ide yang lebih baik tentang di mana menggambar garis.

Dalam kasus ini, Anda dapat memanfaatkan kekuatan utilitas pengujian Angular dan Jasmine untuk menulis tidak hanya tes unit untuk komponen dan layanan, tetapi juga tes UI dasar. Namun, jika Anda perlu menguji fungsionalitas front-end aplikasi Anda dari awal sampai akhir, Protractor adalah cara untuk pergi. Protractor API dikombinasikan dengan pola desain seperti objek halaman membuatnya lebih mudah untuk menulis tes yang lebih mudah dibaca. Berikut ini contoh untuk membuat semuanya berjalan lancar.

1
 /* 

2
  1. It should have a create Paste button

3
  2. Clicking the button should bring up a modal window

4
*/
5
6
it('should have a Create Paste button and modal window', () => {
7
8
    expect(addPastePage.isCreateButtonPresent()).toBeTruthy("The button should exist");
9
    expect(addPastePage.isCreatePasteModalPresent()).toBeFalsy("The modal window shouldn't exist, not yet!");
10
    
11
    addPastePage.clickCreateButton();
12
    
13
    expect(addPastePage.isCreatePasteModalPresent()).toBeTruthy("The modal window should appear now");  
14
});

Mengkonfigurasi Protractor

Menyiapkan Protractor mudah jika Anda menggunakan Angular-CLI untuk menghasilkan proyek Anda. Struktur direktori yang dibuat oleh ng new adalah sebagai berikut.

1
.
2
├── e2e
3
│   ├── app.e2e-spec.ts
4
│   ├── app.po.ts
5
│   └── tsconfig.e2e.json
6
├── karma.conf.js
7
├── package.json
8
├── package-lock.json
9
├── protractor.conf.js
10
├── README.md
11
├── src
12
│   ├── app
13
│   ├── assets
14
│   ├── environments
15
│   ├── favicon.ico
16
│   ├── index.html
17
│   ├── main.ts
18
│   ├── polyfills.ts
19
│   ├── styles.css
20
│   ├── test.ts
21
│   ├── tsconfig.app.json
22
│   ├── tsconfig.spec.json
23
│   └── typings.d.ts
24
├── tsconfig.json
25
└── tslint.json
26
27
5 directories, 19 files

Template proyek default yang dibuat oleh Protractor tergantung pada dua file untuk menjalankan tes: file spesifikasi yang berada di dalam direktori e2e dan file konfigurasi (protractor.conf.js). Mari kita lihat bagaimana protractor.conf.js dapat dikonfigurasi adalah:

1
/* Path: protractor.conf.ts*/
2
3
// Protractor configuration file, see link for more information

4
// https://github.com/angular/protractor/blob/master/lib/config.ts

5
6
const { SpecReporter } = require('jasmine-spec-reporter');
7
8
exports.config = {
9
  allScriptsTimeout: 11000,
10
  specs: [
11
    './e2e/**/*.e2e-spec.ts'
12
  ],
13
  capabilities: {
14
    'browserName': 'chrome'
15
  },
16
  directConnect: true,
17
  baseUrl: 'https://localhost:4200/',
18
  framework: 'jasmine',
19
  jasmineNodeOpts: {
20
    showColors: true,
21
    defaultTimeoutInterval: 30000,
22
    print: function() {}
23
  },
24
  onPrepare() {
25
    require('ts-node').register({
26
      project: 'e2e/tsconfig.e2e.json'
27
    });
28
    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
29
  }
30
};

Jika Anda baik-baik saja dengan menjalankan pengujian di browser web Chrome, Anda dapat membiarkannya seperti ini dan melewati sisa bagian ini.

Mengatur Protractor Dengan Selenium Standalone Server

directConnect: true memungkinkan Protractor terhubung langsung ke driver browser. Namun, pada saat menulis tutorial ini, Chrome adalah satu-satunya browser yang didukung. Jika Anda memerlukan dukungan multi-browser atau menjalankan browser selain Chrome, Anda harus menyiapkan server mandiri Selenium. Langkah-langkahnya adalah sebagai berikut.

Instal Protractor secara global menggunakan npm:

1
npm install -g protractor

Ini menginstal alat baris perintah untuk webdriver-manager bersama dengan protractor. Sekarang perbarui webdriver-manager untuk menggunakan binari terbaru, dan kemudian jalankan server mandiri Selenium.

1
webdriver-manager update
2
3
webdriver-manager start 

Akhirnya, atur directConnect: false dan tambahkan properti seleniumAddress sebagai berikut:

1
capabilities: {
2
    'browserName': 'firefox'
3
  },
4
  directConnect: false,
5
  baseUrl: 'http://localhost:4200/',
6
  seleniumAddress: 'http://localhost:4444/wd/hub',
7
  framework: 'jasmine',
8
  jasmineNodeOpts: {
9
    showColors: true,
10
    defaultTimeoutInterval: 30000,
11
    print: function() {}
12
  },

File konfigurasi di GitHub menyediakan informasi lebih lanjut tentang opsi konfigurasi yang tersedia di Protractor. Saya akan menggunakan opsi default untuk tutorial ini.

Menjalankan Pengujian

ng e2e adalah satu-satunya perintah yang Anda perlukan untuk mulai menjalankan tes jika Anda menggunakan Angular-CLI. Jika tes tampak lambat, itu karena Angular harus mengkompilasi kode setiap kali Anda menjalankan ng e2e. Jika Anda ingin mempercepatnya, inilah yang harus Anda lakukan. Sajikan aplikasi menggunakan ng serve.

Kemudian jalankan tab konsol baru dan jalankan:

1
ng e2e -s false

Tes harus memuat lebih cepat sekarang.

Tujuan Kami

Kami akan menulis tes E2E untuk aplikasi dasar Pastebin. Klon proyek dari repo GitHub.

Baik versi, versi starter (yang tanpa tes) dan versi final (yang dengan tes), tersedia di cabang terpisah. Mengkloning cabang pemula untuk saat ini. Secara opsional, layani proyek dan ikuti kode untuk berkenalan dengan aplikasi yang ada di tangan.

Mari kita gambarkan aplikasi Pastebin kita sebentar. Aplikasi ini awalnya akan memuat daftar pastes (diambil dari server tiruan) ke dalam tabel. Setiap baris dalam tabel akan memiliki tombol View Paste yang, ketika diklik, membuka jendela modal bootstrap. Jendela modal menampilkan data paste dengan opsi untuk mengedit dan menghapus paste. Menjelang ujung meja, ada tombol Create Paste yang dapat digunakan untuk menambahkan pastes baru.

End-to-End testing using protractor Sample pastebin applicationEnd-to-End testing using protractor Sample pastebin applicationEnd-to-End testing using protractor Sample pastebin application
Contoh Aplikasi.

Sisa dari tutorial ini didedikasikan untuk menulis tes Protractor di Angular.

Dasar Protractor

File spek, yang diakhiri dengan .e2e-spec.ts, akan menghosting tes yang sebenarnya untuk aplikasi kita. Kami akan menempatkan semua spesifikasi pengujian di dalam direktori e2e karena itulah tempat kami mengkonfigurasi Protractor untuk mencari spesifikasi.

Ada dua hal yang perlu Anda pertimbangkan saat menulis tes Protractor:

  • Sintaks Jasmine
  • Protractor API

Sintaks Jasmine

Buat file baru bernama test.e2e-spec.ts dengan kode berikut untuk memulai.

1
/* Path: e2e/test.e2e-spec.ts */
2
3
import { browser, by, element } from 'protractor';
4
5
describe('Protractor Demo', () => {
6
 
7
  beforeEach(() => {
8
    //The code here will get executed before each it block is called  

9
    //browser.get('/');

10
  });
11
12
  it('should display the name of the application',() => {
13
   /*Expectations accept parameters that will be matched with the real value

14
   using Jasmine's matcher functions. eg. toEqual(),toContain(), toBe(), toBeTruthy() etc. */
15
   expect("Pastebin Application").toEqual("Pastebin Application");
16
   
17
  });
18
  
19
  it('should click the create Paste button',() => {
20
    //spec goes here

21
   
22
  });
23
});

Ini menggambarkan bagaimana pengujian kami akan diatur di dalam file spesifikasi menggunakan sintaks Jasmine. describe(), beforeEach() dan it() adalah fungsi Jasmine global.

Jasmine memiliki sintaks yang bagus untuk menulis tes, dan bekerja sama dengan Protractor. Jika Anda baru mengenal Jasmine, saya akan merekomendasikan untuk menelusuri halaman GitHub Jasmine terlebih dahulu.

describe blok digunakan untuk membagi tes menjadi rangkaian uji logis. Setiap describe blok (atau rangkaian tes) dapat memiliki it beberapa blok (atau uji spesifikasi). Tes yang sebenarnya didefinisikan di dalam spesifikasi tes.

"Mengapa saya harus menyusun tes saya dengan cara ini?" Anda mungkin bertanya. Sebuah rangkaian tes dapat digunakan untuk secara logis menggambarkan fitur tertentu dari aplikasi Anda. Misalnya, semua spesifikasi yang berkaitan dengan komponen Pastebin idealnya harus dibahas di dalam blok mendeskripsikan berjudul Halaman Pastebin. Meskipun ini dapat menghasilkan tes yang berlebihan, tes Anda akan lebih mudah dibaca dan dipelihara.

Blok mendeskripsikan dapat memiliki metode beforeEach() yang akan dijalankan satu kali, sebelum setiap spesifikasi di blok itu. Jadi, jika Anda perlu browser untuk menavigasi ke URL sebelum setiap tes, menempatkan kode untuk navigasi di dalam beforeEach() adalah hal yang benar untuk dilakukan.

Ekspektasikan pernyataan, yang menerima nilai, dirangkai dengan beberapa fungsi matcher. Baik nilai nyata dan nilai yang diharapkan dibandingkan, dan boolean dikembalikan yang menentukan apakah pengujian gagal atau tidak.

Protractor API

Sekarang, mari taruh daging di atasnya.

1
/* Path: e2e/test.e2e-spec.ts */
2
3
import { browser, by, element } from 'protractor';
4
5
describe('Protractor Demo', () => {
6
 
7
  beforeEach(() => {
8
    browser.get('/');
9
  });
10
11
  it('should display the name of the application',() => {
12
   
13
    expect(element(by.css('.pastebin')).getText()).toContain('Pastebin Application');
14
   
15
  });
16
  
17
  it('create Paste button should work',() => {
18
   
19
    expect(element(by.id('source-modal')).isPresent()).toBeFalsy("The modal window shouldn't appear right now ");
20
    element(by.buttonText('create Paste')).click();
21
    expect(element(by.id('source-modal')).isPresent()).toBeTruthy('The modal window should appear now');
22
   
23
  });
24
});

browser.get('/') dan element(by.css('.pastebin')).getText() adalah bagian dari Protractor API. Mari dapati tangan kita kotor dan melompat tepat ke apa yang ditawarkan Protractor.

Komponen utama yang diekspor oleh Protractor API tercantum di bawah ini.

  1. browser(): Anda harus memanggil browser() untuk semua operasi tingkat browser seperti navigasi, debugging, dll.
  2. element(): Ini digunakan untuk mencari elemen di DOM berdasarkan kondisi pencarian atau rantai kondisi. Ini mengembalikan objek ElementFinder, dan Anda dapat melakukan tindakan seperti getText() atau click() pada mereka.
  3. element.all(): Ini digunakan untuk mencari berbagai elemen yang cocok dengan beberapa rantai kondisi. Ini mengembalikan objek ElementArrayFinder. Semua tindakan yang dapat dilakukan pada ElementFinder dapat dilakukan pada ElementArrayFinder juga.
  4. locators: Locators menyediakan metode untuk menemukan elemen dalam aplikasi Angular.

Karena kami akan menggunakan pencari sangat sering, berikut adalah beberapa pencari yang umum digunakan.

  • by.css('selector-name'): Ini sejauh ini adalah pencari yang umum digunakan untuk menemukan elemen berdasarkan nama selector CSS.
  • by.name('name-value'): Menempatkan elemen dengan nilai yang cocok untuk atribut nama.
  • by.buttonText('button-value'): Menempatkan elemen tombol atau array elemen tombol berdasarkan teks bagian dalam.

Catatan: Locators by.model, by.binding dan by.repeater tidak bekerja dengan aplikasi Angular 2+ pada saat menulis tutorial ini. Gunakan pencari berbasis CSS sebagai gantinya.

Mari tulis lebih banyak tes untuk aplikasi Pastebin kami.

1
 it('should accept and save input values', () => {
2
      element(by.buttonText('create Paste')).click();
3
4
      //send input values to the form using sendKeys

5
     
6
      element(by.name('title')).sendKeys('Hello world in Ruby');
7
      element(by.name('language')).element(by.cssContainingText('option', 'Ruby')).click();
8
      element(by.name('paste')).sendKeys("puts 'Hello world';");
9
10
      element(by.buttonText('Save')).click();
11
12
      //expect the table to contain the new paste

13
      const lastRow = element.all(by.tagName('tr')).last();
14
      expect(lastRow.getText()).toContain("Hello world in Ruby");
15
});

Kode di atas berfungsi, dan Anda dapat memverifikasi sendiri. Namun, tidakkah Anda merasa lebih nyaman menulis tes tanpa kosakata Protractor-spesifik dalam file spesifikasi Anda? Inilah yang saya bicarakan:

1
 it('should have an Create Paste button and modal window', () => {
2
3
    expect(addPastePage.isCreateButtonPresent()).toBeTruthy("The button should exist");
4
    expect(addPastePage.isCreatePasteModalPresent()).toBeFalsy("The modal window shouldn't appear, not yet!");
5
    
6
    addPastePage.clickCreateButton();
7
    
8
    expect(addPastePage.isCreatePasteModalPresent()).toBeTruthy("The modal window should appear now");
9
   
10
11
  });
12
  
13
 it('should accept and save input values', () => {
14
   
15
    addPastePage.clickCreateButton();
16
     
17
    //Input field should be empty initially

18
    const emptyInputValues = ["","",""];
19
    expect(addPastePage.getInputPasteValues()).toEqual(emptyInputValues);
20
    
21
    //Now update the input fields

22
    addPastePage.addNewPaste();
23
    
24
    addPastePage.clickSaveButton();
25
 
26
    expect(addPastePage.isCreatePasteModalPresent()).toBeFalsy("The modal window should be gone");
27
    expect(mainPage.getLastRowData()).toContain("Hello World in Ruby");
28
29
  });

Spesifikasi tampak lebih jelas tanpa bagasi Protractor ekstra. Bagaimana saya melakukannya? Izinkan saya memperkenalkan Anda ke Halaman Objek.

Halaman Objek

Halaman Objek adalah pola desain yang populer di lingkaran otomatisasi pengujian. Sebuah objek halaman memodelkan suatu halaman atau bagian dari aplikasi yang menggunakan kelas berorientasi objek. Semua objek (yang relevan dengan pengujian kami) seperti teks, judul, tabel, tombol, dan tautan dapat ditangkap dalam objek halaman. Kami kemudian dapat mengimpor objek halaman ini ke dalam file spesifikasi dan menjalankan metode mereka. Ini mengurangi duplikasi kode dan membuat pemeliharaan kode lebih mudah.

Buat direktori bernama page-objects dan tambahkan file baru di dalamnya yang disebut pastebin.po.ts. Semua objek yang berkaitan dengan komponen Pastebin akan ditangkap di sini. Seperti yang disebutkan sebelumnya, kami membagi seluruh aplikasi menjadi tiga komponen yang berbeda, dan setiap komponen akan memiliki objek halaman yang didedikasikan untuk itu. Skema penamaan .po.ts adalah murni konvensional, dan Anda dapat menamainya apa pun yang Anda inginkan.

Ini adalah cetak biru dari halaman yang sedang kami uji.

End-to-End Testing in Angular Blueprint for the Pastebin componentEnd-to-End Testing in Angular Blueprint for the Pastebin componentEnd-to-End Testing in Angular Blueprint for the Pastebin component

Ini kodenya.

pastebin.po.ts

1
/* Path e2e/page-objects/pastebin.po.ts*/
2
3
import { browser, by, element, promise, ElementFinder, ElementArrayFinder } from 'protractor';
4
5
6
export class Pastebin extends Base {
7
    
8
    navigateToHome():promise.Promise<any> {
9
        return browser.get('/');
10
    }
11
    
12
	getPastebin():ElementFinder {
13
		return element(by.css('.pastebin'));
14
	}
15
16
	/* Pastebin Heading */
17
	getPastebinHeading(): promise.Promise<string> {
18
		return this.getPastebin().element(by.css("h2")).getText();
19
	}
20
21
	/*Table Data */
22
23
	getTable():ElementFinder {
24
		return this.getTable().element(by.css('table'));
25
26
	}
27
28
	getTableHeader(): promise.Promise<string> {
29
		return this.getPastebin().all(by.tagName('tr')).get(0).getText();
30
	}
31
32
	getTableRow(): ElementArrayFinder {
33
		return this.getPastebin().all(by.tagName('tr'));
34
	}
35
36
	
37
	getFirstRowData(): promise.Promise<string> {
38
		return this.getTableRow().get(1).getText();
39
	}
40
41
	getLastRowData(): promise.Promise<string> {
42
		return this.getTableRow().last().getText();
43
	}
44
45
	/*app-add-paste tag*/
46
47
	getAddPasteTag(): ElementFinder {
48
		return this.getPastebin().element(by.tagName('app-add-paste'));
49
	}
50
51
	isAddPasteTagPresent(): promise.Promise<boolean> {
52
		return this.getAddPasteTag().isPresent();
53
	}
54
55
}

Mari kita bahas apa yang telah kita pelajari sejauh ini. API Protractor mengembalikan objek, dan kami telah menemukan tiga jenis objek sejauh ini. Mereka:

  • promise.Promise
  • ElementFinder
  • ElementArrayFinder

Singkatnya, element() mengembalikan ElementFinder, dan element().all mengembalikan ElementArrayFinder. Anda dapat menggunakan locators (by.css, by.tagName, dll.) Untuk menemukan lokasi elemen di DOM dan meneruskannya ke element() atau element.all().

ElementFinder dan ElementArrayFinder kemudian dapat dikaitkan dengan tindakan, seperti isPresent(), getText(), click(), dll. Metode-metode ini mengembalikan promise yang akan diselesaikan ketika tindakan tertentu telah selesai.

Alasan mengapa kita tidak memiliki rantai then() dalam pengujian kami adalah karena Protractor mengurusnya secara internal. Tes tampak sinkron meskipun tidak; oleh karena itu, hasil akhirnya adalah pengalaman pengkodean linier. Namun, saya sarankan menggunakan sintaks async/await untuk memastikan bahwa kode tersebut adalah bukti masa depan.

Anda dapat menukar beberapa objek ElementFinder, seperti yang ditunjukkan di bawah ini. Ini sangat membantu jika DOM memiliki banyak pemilih dengan nama yang sama dan kita harus menangkap yang benar.

1
    getTable():ElementFinder {
2
        return this.getPastebin().element(by.css('table'));
3
4
	}

Sekarang kita memiliki kode untuk objek halaman siap, mari kita impor ke spec kami. Ini kode untuk tes awal kami.

1
/* Path: e2e/mainPage.e2e-spec.ts */
2
3
import { Pastebin } from './page-objects/pastebin.po';
4
import { browser, protractor } from 'protractor';
5
6
7
/* Scenarios to be Tested 

8
  1. Pastebin Page should display a heading with text Pastebin Application 

9
  2. It should have a table header

10
  3. The table should have rows

11
  4. app-add-paste tag should exist

12
*/
13
14
describe('Pastebin Page', () => {
15
 
16
  const mainPage: Pastebin = new Pastebin();
17
18
  beforeEach(() => {
19
      mainPage.navigateToHome();
20
  });
21
22
  it('should display the heading Pastebin Application', () => {
23
    
24
      expect(mainPage.getPastebinHeading()).toEqual("Pastebin Application");
25
26
     
27
  });
28
29
   it('should have a table header', () => {
30
  
31
      expect(mainPage.getTableHeader()).toContain("id Title Language Code");
32
     
33
  })
34
  it('table should have at least one row', () => {
35
    
36
      expect(mainPage.getFirstRowData()).toContain("Hello world");
37
  })
38
  
39
  it('should have the app-add-paste tag', () => {
40
      expect(mainPage.isAddPasteTagPresent()).toBeTruthy();
41
  })
42
});

Mengorganisir Tes dan Refactoring

Tes harus diatur sedemikian rupa sehingga struktur keseluruhan tampak bermakna dan lugas. Berikut adalah beberapa panduan yang dianjurkan yang harus Anda ingat saat mengatur tes E2E.

  • Tes E2E terpisah dari tes unit.
  • Kelompokkan tes E2E Anda dengan bijaksana. Atur tes Anda dengan cara yang sesuai dengan struktur proyek Anda.
  • Jika ada beberapa halaman, objek halaman harus memiliki direktori terpisah sendiri.
  • Jika objek halaman memiliki beberapa metode yang sama (seperti navigasiToHome()), buat objek halaman dasar. Model halaman lain dapat mewarisi dari model halaman dasar.
  • Buat tes Anda independen satu sama lain. Anda tidak ingin semua tes Anda gagal karena perubahan kecil di UI, bukan?
  • Jaga definisi objek halaman bebas dari assertions/expectations. Pernyataan harus dibuat di dalam file spesifikasi.

Mengikuti panduan di atas, inilah hirarki objek halaman dan organisasi file yang akan terlihat.

Page object hierarchy and e2e test structure in ProtractorPage object hierarchy and e2e test structure in ProtractorPage object hierarchy and e2e test structure in Protractor

Kami sudah membahas pastebin.po.ts dan mainPage.e2e-spec.ts. Berikut ini file-file sisanya.

Objek Halaman Dasar

1
/* path: e2e/page-objects/base.po.ts */
2
3
import { browser, by, element, promise, ElementFinder, ElementArrayFinder } from 'protractor';
4
5
export class Base {
6
7
    /* Navigational methods */
8
	navigateToHome():promise.Promise<any> {
9
    	return browser.get('/');
10
  	}
11
12
  	navigateToAbout():promise.Promise<any>  {
13
  	 	return browser.get('/about');
14
  	}
15
16
  	navigateToContact():promise.Promise<any>  {
17
  		return browser.get('/contact');
18
  	}
19
20
  	/* Mock data for creating a new Paste and editing existing paste */
21
22
	getMockPaste(): any {
23
		let paste: any = { title: "Something  here",language: "Ruby",paste: "Test"}
24
  		return paste;
25
	}
26
27
	getEditedMockPaste(): any {
28
		let paste: any = { title: "Paste 2", language: "JavaScript", paste: "Test2" }
29
		return paste;
30
	}
31
	
32
	/* Methods shared by addPaste and viewPaste */
33
34
	getInputTitle():ElementFinder {
35
		return element(by.name("title"));
36
	}
37
38
	getInputLanguage(): ElementFinder {
39
		return element(by.name("language"));
40
	}
41
42
	getInputPaste(): ElementFinder {
43
		return element(by.name("paste"));
44
45
	}
46
}

Tambahkan Paste Objek Halaman

End-to-End Testing in Angular Blueprint for the AddPaste componentEnd-to-End Testing in Angular Blueprint for the AddPaste componentEnd-to-End Testing in Angular Blueprint for the AddPaste component
Cetak biru untuk komponen AddPaste
1
/* Path: e2e/page-objects/add-paste.po.ts */
2
3
import { browser, by, element, promise, ElementFinder, ElementArrayFinder } from 'protractor';
4
import { Base } from './base.po';
5
export class AddPaste extends Base  {
6
    
7
	getAddPaste():ElementFinder {
8
		return element(by.tagName('app-add-paste'));
9
	}
10
	
11
	/* Create Paste button */
12
	getCreateButton(): ElementFinder {
13
		return this.getAddPaste().element(by.buttonText("create Paste"));
14
	}
15
16
	isCreateButtonPresent() : promise.Promise<boolean> {
17
		return this.getCreateButton().isPresent();
18
	}
19
20
	clickCreateButton(): promise.Promise<void> {
21
		return this.getCreateButton().click();
22
	}
23
24
	/*Create Paste Modal */
25
26
	getCreatePasteModal(): ElementFinder {
27
		return this.getAddPaste().element(by.id("source-modal"));
28
	}
29
30
	isCreatePasteModalPresent() : promise.Promise<boolean> {
31
		return this.getCreatePasteModal().isPresent();
32
	}
33
34
	/*Save button */
35
	getSaveButton(): ElementFinder {
36
		return this.getAddPaste().element(by.buttonText("Save"));
37
	}
38
	
39
	clickSaveButton():promise.Promise<void> {
40
		return this.getSaveButton().click();
41
	}
42
43
	/*Close button */
44
45
	getCloseButton(): ElementFinder {
46
		return this.getAddPaste().element(by.buttonText("Close"));
47
	}
48
49
	clickCloseButton():promise.Promise<void> {
50
		return this.getCloseButton().click();
51
	}
52
	
53
54
	/* Get Input Paste values from the Modal window */
55
	getInputPasteValues(): Promise<string[]> {
56
		let inputTitle, inputLanguage, inputPaste;
57
58
		// Return the input values after the promise is resolved

59
		// Note that this.getInputTitle().getText doesn't work

60
		// Use getAttribute('value') instead

61
		return Promise.all([this.getInputTitle().getAttribute("value"), this.getInputLanguage().getAttribute("value"), this.getInputPaste().getAttribute("value")])
62
		.then( (values) => {
63
			return values;
64
		});
65
		
66
	}
67
68
	/* Add a new Paste */
69
70
	addNewPaste():any {
71
		let newPaste: any = this.getMockPaste();
72
73
		//Send input values

74
		this.getInputTitle().sendKeys(newPaste.title);
75
		this.getInputLanguage()
76
			.element(by.cssContainingText('option', newPaste.language)).click();
77
		this.getInputPaste().sendKeys(newPaste.paste);
78
79
		//Convert the paste object into an array

80
  		return Object.keys(newPaste).map(key => newPaste[key]);
81
82
	}
83
84
}

Tambahkan file Paste Spec

1
/* Path: e2e/addNewPaste.e2e-spec.ts */
2
3
import { Pastebin } from './page-objects/pastebin.po';
4
import { AddPaste } from './page-objects/add-paste.po';
5
import { browser, protractor } from 'protractor';
6
7
/* Scenarios to be Tested 

8
  1. AddPaste Page should have a button when clicked on should present a modal window 

9
  2. The modal window should accept the new values and save them

10
  4. The saved data should appear in the MainPage

11
  3. Close button should work

12
*/
13
14
describe('Add-New-Paste page', () => {
15
 
16
  const addPastePage: AddPaste = new AddPaste();
17
  const mainPage: Pastebin = new Pastebin();
18
19
  beforeEach(() => {
20
 
21
    addPastePage.navigateToHome();
22
  });
23
24
  it('should have an Create Paste button and modal window', () => {
25
26
    expect(addPastePage.isCreateButtonPresent()).toBeTruthy("The button should exist");
27
    expect(addPastePage.isCreatePasteModalPresent()).toBeFalsy("The modal window shouldn't appear, not yet!");
28
    
29
    addPastePage.clickCreateButton();
30
    
31
    expect(addPastePage.isCreatePasteModalPresent()).toBeTruthy("The modal window should appear now");
32
   
33
34
  });
35
36
  it("should accept and save input values", () => {
37
   
38
    addPastePage.clickCreateButton();
39
     
40
    const emptyInputValues = ["","",""];
41
    expect(addPastePage.getInputPasteValues()).toEqual(emptyInputValues);
42
    
43
    const newInputValues = addPastePage.addNewPaste();
44
    expect(addPastePage.getInputPasteValues()).toEqual(newInputValues);
45
46
    addPastePage.clickSaveButton();
47
 
48
    expect(addPastePage.isCreatePasteModalPresent()).toBeFalsy("The modal window should be gone");
49
    expect(mainPage.getLastRowData()).toContain("Something here");
50
51
  });
52
53
  it("close button should work", () => {
54
    
55
    addPastePage.clickCreateButton();
56
    addPastePage.clickCloseButton();
57
    
58
    expect(addPastePage.isCreatePasteModalPresent()).toBeFalsy("The modal window should be gone");
59
     
60
  });
61
  
62
});

Latihan

Ada beberapa hal yang hilang, meskipun: tes untuk tombol View Paste dan jendela modal yang muncul setelah mengklik tombol. Saya akan meninggalkan ini sebagai latihan untuk Anda. Namun, saya akan memberi Anda petunjuk.

Struktur objek halaman dan spesifikasi untuk ViewPastePage mirip dengan yang ada pada AddPastePage.

End-to-End Testing in Angular Blueprint for ViewPaste componentEnd-to-End Testing in Angular Blueprint for ViewPaste componentEnd-to-End Testing in Angular Blueprint for ViewPaste component
Cetak biru untuk komponen ViewPaste

Berikut adalah skenario yang perlu Anda uji:

  1. Halaman ViewPaste harus memiliki sebuah tombol, dan pada klik, itu akan memunculkan jendela modal.
  2. Jendela modal harus menampilkan data tempel dari paste yang baru ditambahkan.
  3. Jendela modal harus membiarkan Anda memperbarui nilai.
  4. Tombol hapus seharusnya berfungsi.

Cobalah untuk tetap berpegang pada pedoman sedapat mungkin. Jika Anda ragu, alihkan ke cabang terakhir untuk melihat draf terakhir dari kode.

Membungkusnya

Jadi begitulah. Dalam artikel ini, kami telah membahas penulisan tes end-to-end untuk aplikasi Angular kami menggunakan Protractor. Kami memulai dengan diskusi tentang tes unit vs. tes e2e, dan kemudian kami belajar tentang pengaturan, konfigurasi dan menjalankan Protractor. Sisa dari tutorial berkonsentrasi pada penulisan tes yang sebenarnya untuk aplikasi demo Pastebin.

Tolong beri tahu saya pemikiran dan pengalaman Anda tentang menulis tes menggunakan Protractor atau tes tertulis untuk Angular secara umum. Saya akan senang mendengarnya. Terima kasih sudah membaca!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.