In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/03 Report--
This paper introduces the configuration and testing methods of Angular 7 unit test and E2E test. Using Angular CLI to build a new project, the basic test environment has been configured and the test sample code has been generated. By default, Angular unit tests use the Jasmine test framework and the Karma test runner, and E2E tests use the Jasmine and Protractor test frameworks.
Configure unit tests
Jasmine is a behavior-driven (Behavior-Driven) framework for testing JavaScript and does not depend on any other JavaScript framework.
Karma is a test runner, which provides developers with an efficient and real test environment, supports a variety of browsers and is easy to debug.
Configuration file
Unit test configuration files test.ts and karma.conf.js:
Test.ts
Import 'zone.js/dist/zone-testing';import {getTestBed} from' @ angular/core/testing';import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from'@ angular/platform-browser-dynamic/testing';declare const require: any;// First, initialize the Angular testing environment.getTestBed () .initTestEnvironment (BrowserDynamicTestingModule, platformBrowserDynamicTesting ()); / / Then we find all the tests.const context = require.context ('. /', true, /\ .spec\ .ts $/); / / And load the modules.context.keys () .map (context)
By default, the test file extension must be .spec.ts.
Karma.conf.js
Module.exports = function (config) {config.set ({basePath:', frameworks: ['jasmine',' @ angular-devkit/build-angular'], plug × ×: [require ('karma-jasmine'), require (' karma-chrome-launcher'), require ('karma-jasmine-html-reporter'), require (' karma-coverage-istanbul-reporter')) Require ('@ angular-devkit/build-angular/plug × × / karma')], client: {clearContext: false / / leave Jasmine Spec Runner output visible in browser}, coverageIstanbulReporter: {dir: require ('path'). Join (_ _ dirname,'.. / coverage'), reports: ['html',' lcovonly'], fixWebpackSourcePaths: true}, reporters: ['progress',' kjhtml'], port: 9876 Colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false}) }
By default, using the Chrome browser, unit test reports and coverage reports can be generated, coverage reports are saved in the root directory coverage folder, and autoWatch is enabled.
SingleRun defaults to false. If set to true, it will automatically exit after the test and return code 0 or 1 according to the test result. It is commonly used in CI environment.
Browser configuration
Browsers supported by Karma:
ChromeChromeCanaryChromeHeadlessPhantomJSFirefoxOperaIESafari
Multiple browsers can be configured for testing at the same time. To enable other browsers, you need to install dependencies, such as enabling Firefox:
Npm I karma-firefox-launcher-- save-dev
Then add the configuration within the karma.conf.js:
... require ('karma-chrome-launcher'), require (' karma-firefox-launcher'),... browsers: ['Chrome',' Firefox'],... Run the test
Create an App with CLI to generate a unit test file app.component.spec.ts. Execute the CLI command ng test to run the unit test:
Ng test
After running, output the test results in the console and open the browser:
The browser will display the test results, total number of tests, and number of failures. At the top, each point or fork corresponds to a test case, the dot indicates success, the fork indicates failure, and the mouse over the point or fork displays the test information. Click on a line in the test results to rerun a test or a set of (test suite) tests.
Common parameters:
-- browsers specifies the browser to use
-- code-coverage output coverage report
-- code-coverage-exclude excludes files or paths
-- karma-config specifies the Karma profile
-- prod enables production environment
-- progress defaults to true, which outputs the compilation progress to the console
-- watch defaults to true, and the test will be rerun after code modification
Custom Launcher
Karma-chrome-launcher, karma-firefox-launcher, karma-ie-launcher, etc. all support custom Launcher,customLaunchers combined with-- browsers to meet the testing needs of a variety of environments. For custom properties supported by each browser, please refer to the Karma Browsers documentation.
For example, Headless mode is commonly used in CI environment, and the browser interface is not needed. The following configuration is added to karma.conf.js:
Browsers: ['Chrome'], customLaunchers: {ChromeHeadlessCI: {base:' ChromeHeadless', flags: ['- no-sandbox']}}
Run the following command to test:
Ng test-watch=false-progress=false-browsers=ChromeHeadlessCI test coverage
Run the following command to generate the test coverage report, which is saved in the coverage folder under the root of the project:
Ng test-watch=false-code-coverage
If you want to generate a report for each test, modify the CLI configuration file angular.json:
"test": {"options": {"codeCoverage": true}}
Set excluded files or paths
Ng test-watch=false-code-coverage--code-coverage-exclude=src/app/heroes/heroes.component.ts-code-coverage-exclude=src/app/hero-search/*
It can also be configured in angular.json:
"test": {"options": {"codeCoverage": true, "codeCoverageExclude": ["src/app/heroes/heroes.component.ts", "src/app/hero-search/*"]}}
Set test coverage indicators
Edit the configuration file karma.conf.js by adding the following:
CoverageIstanbulReporter: {reports: ['html',' lcovonly'], fixWebpackSourcePaths: true, thresholds: {statements: 80, lines: 80, branches: 80, functions: 80}}
The background that meets the standard in the test report is green:
Note: do not set coverage metrics when integrating with CI, otherwise Job will be terminated if the metrics are not reached.
LCOV
The reports parameter in coverageIstanbulReporter is ['html',' lcovonly'], which generates reports in both html and lcov formats. The report file lcov.info can be integrated with Sonar, and the LCOV Files path can be configured in the Sonar management interface to view the test in Sonar.
In addition, when integrating with Sonar, you need to configure TypeScript Exclusions to exclude .spec.ts, otherwise the test file will be included in the statistical coverage.
Write the first test
Test files are automatically created when you use CLI to create Service, Component, etc. Let's take the test file app.component.spec.ts generated when creating App as an example:
Import {async, TestBed} from'@ angular/core/testing';import {RouterTestingModule} from'@ angular/router/testing';import {AppComponent} from'. / app.component';describe ('AppComponent', () = > {beforeEach (async () = > {TestBed.configureTestingModule ({imports: [RouterTestingModule], declarations: [AppComponent],}) .compileComponents ();})) It ('should create the app', () = > {const fixture = TestBed.createComponent (AppComponent); const app = fixture.debugElement.componentInstance; expect (app). ToBeTruthy ();}); it (`should have as title' hello' `, () = > {const fixture = TestBed.createComponent (AppComponent); const app = fixture.debugElement.componentInstance; expect (app.title) .toEqual ('hello');}) It ('should render title in a H2 tag', () = > {const fixture = TestBed.createComponent (AppComponent); fixture.detectChanges (); const compiled = fixture.debugElement.nativeElement; expect (compiled.querySelector (' H2') .textContent) .toContain ('Welcome to hellograms');})
Test structure
From the above example, we can understand the main structure of the test:
The describe function contains two types of functions: beforeEach and it. Describe is equivalent to the suite in Java testing, that is, the test group, which can contain multiple test cases it. Generally, a test file contains one describe, but of course there can be more than one. BeforeEach is the equivalent of the @ Before method in Java tests and is called once before each test case is executed. Similarly, there are afterEach, beforeAll, and afterAll functions. AfterEach is called once after each test case is executed. BeforeAll and afterAll are equivalent to @ BeforeClass and @ AfterClass methods in Java tests, and are called once before and after each describe execution.
The first parameter for describe and it is the test description. An it can contain one or more expect to perform test verification.
TestBed
TestBed is the most important tool in Angular testing.
The TestBed.configureTestingModule () method dynamically builds TestingModule to simulate Angular @ NgModule, which supports most of the attributes of @ NgModule.
The components and dependencies of the test need to be imported in the test. Router-outlet is used in the AppComponent page, so we imported RouterTestingModule to simulate RouterModule. Test Module is preconfigured with some elements, such as BrowserModule, which do not need to be imported.
The TestBed.createComponent () method creates a component instance and returns ComponentFixture. ComponentFixture is a testing tool (test harness) for interacting with components and corresponding elements that are created.
NativeElement and DebugElement
Fixture.debugElement.nativeElement is used in the example, or it can be written as fixture.nativeElement. In fact, fixture.nativeElement is a simplified way to write fixture.debugElement.nativeElement. NativeElement relies on the runtime environment, and Angular relies on DebugElement abstractions to support cross-platform support. Angular creates a DebugElement tree to wrap native element,nativeElement 's return platform-related element objects.
Our test sample runs only in the browser, so the nativeElement is always HTMLElement, and you can use the querySelector () and querySelectorAll () methods to query the elements.
Element.querySelector ('p'); element.querySelector ('input'); element.querySelector ('. Span''); element.querySelectorAll ('span')
DetectChanges
The createComponent () function does not bind data, and you must call fixture.detectChanges () to perform data binding in order to get the content in the component element:
It ('should render title in a H2 tag', () = > {const fixture = TestBed.createComponent (AppComponent); fixture.detectChanges (); const compiled = fixture.debugElement.nativeElement; expect (compiled.querySelector (' H2') .textContent) .toContain ('Welcome to hellograms');})
When the data model value changes, you also need to call the fixture.detectChanges () method:
It ('should render title ina H2 tag', () = > {const fixture = TestBed.createComponent (AppComponent); const app = fixture.componentInstance; app.title =' china'; fixture.detectChanges (); const compiled = fixture.nativeElement; expect (compiled.querySelector ('H2') .textContent). ToContain ('Welcome to porcelain');})
Automatic detection can be configured to add ComponentFixtureAutoDetect provider:
Import {ComponentFixtureAutoDetect} from'@ angular/core/testing';...TestBed.configureTestingModule ({providers: [{provide: ComponentFixtureAutoDetect, useValue: true}]})
When automatic detection is enabled, you only need to call detectChanges () after the value has changed:
It ('should display original title', ()) = > {/ / Hooray! No `fixture.detectChanges () `needed expect (h2.textContent) .toContain (comp.title); it ('should still see original title after comp.title change', () = > {const oldTitle = comp.title; comp.title =' Test Title'; / / Displayed title is old because Angular didn't hear the change: (expect (h2.textContent) .toContain (oldTitle);}); it ('should display updated title after detectChanges', () = > {comp.title =' Test Title'; fixture.detectChanges ()) / / detect changes explicitly expect (h2.textContent) .toContain (comp.title);})
Synchronous and asynchronous beforeEach
Components often use the @ Component.templateUrl and @ Component.styleUrls attributes to specify that external templates and CSS,Angular compilers read external files during compilation.
@ Component ({selector: 'app-banner', templateUrl:'. / banner-external.component.html', styleUrls: ['. / banner-external.component.css']}) beforeEach () = > {TestBed.configureTestingModule ({declarations: [BannerComponent],}); fixture = TestBed.createComponent (BannerComponent);})
There is no problem when running a test with the synchronous beforeEach method as described above with the ng test command of CLI, because the test is compiled before running it. Running these tests in a non-CLI environment may fail. To solve this problem, you can call compileComponents () to compile the display. The compileComponents () method is asynchronous and must be called in the async () method:
BeforeEach (async () = > {TestBed.configureTestingModule ({imports: [RouterTestingModule], declarations: [AppComponent],}) .compileComponents ()
Calling compileComponents () closes the current TestBed instance, no longer allows configuration, and cannot call any configuration methods in TestBed. Neither configureTestingModule () nor any override... can be called. Method.
Synchronous beforeEach and asynchronous beforeEach are often used to work together, asynchronous beforeEach () is responsible for compiling components, and synchronous beforeEach () is responsible for executing the rest of the preparation code. The test runner calls the asynchronous beforeEach method first, and then calls the synchronous method after it has been run.
Reconstruct
There is a lot of repetitive code in the example, so let's simplify it with two beforeEach:
Import {async, ComponentFixture, TestBed} from'@ angular/core/testing';import {RouterTestingModule} from'@ angular/router/testing';import {AppComponent} from'. / app.component';describe ('AppComponent', () = > {let fixture: ComponentFixture; let app: AppComponent; beforeEach (async () = > {TestBed.configureTestingModule ({imports: [RouterTestingModule], declarations: [AppComponent],}) .compileComponents () BeforeEach (() = > {fixture = TestBed.createComponent (AppComponent); app = fixture.componentInstance; fixture.detectChanges ();}); it ('should create the app', () = > {expect (app). ToBeTruthy ();}); it (`should have as title' hello' `, () = > {expect (app.title) .toEqual ('hello');}); it (' should render title in a H2 tag', () = > {const compiled = fixture.nativeElement) Expect (compiled.querySelector ('H2') .textContent) .toContain ('Welcome to hellographies');});})
You can also reconstruct the two beforeEach () into an asynchronous beforeEach ():
BeforeEach (async () = > {TestBed.configureTestingModule ({imports: [RouterTestingModule], declarations: [AppComponent],}) .accouneComponents () .then (() = > {fixture = TestBed.createComponent (AppComponent); app = fixture.componentInstance; fixture.detectChanges ();}); dependency injection and Mock
By testing simple objects, you can create instances with new:
Describe ('ValueService', () = > {let service: ValueService; beforeEach (() = > {service = new ValueService ();});...})
However, most Service, Component, and so on have multiple dependencies, so it is not convenient to use new. If you use DI to create test objects, when you rely on other services, DI will find or create dependent services. To test an object, configure the test object itself and its dependencies in configureTestingModule, and then call TestBed.get () to inject the test object:
BeforeEach (() = > {TestBed.configureTestingModule ({providers: [ValueService]}); service = TestBed.get (ValueService);})
One of the principles of unit testing: only test the object itself, but not its dependencies, and the dependencies are injected through mock without using the actual object, otherwise the test is out of control.
Mock gives priority to Spy:
Let masterService: MasterService;beforeEach (() = > {const spy = jasmine.createSpyObj ('ValueService', [' getValue']); spy.getValue.and.returnValue ('stub value'); TestBed.configureTestingModule ({/ / Provide both the service-to-test and its (spy) dependency providers: [MasterService, {provide: ValueService, useValue: spy}]}); masterService = TestBed.get (MasterService);}); HttpClient, Router, Location
Just like testing objects with other dependencies, you can mock HttpClient, Router, Location:
BeforeEach (() = > {const httpClientSpy = jasmine.createSpyObj ('HttpClient', [' get']); TestBed.configureTestingModule ({providers: [{provide: HttpClient, useValue: httpClientSpy}]});}); beforeEach (async () = > {const routerSpy = jasmine.createSpyObj ('Router', [' navigateByUrl']); const locationSpy = jasmine.createSpyObj ('Location', [' back']) TestBed.configureTestingModule ({providers: [{provide: Router, useValue: routerSpy}, {provide: Location, useValue: locationSpy}]}) .componeComponents (); Component test only tests component classes
Testing a component class is as simple as testing a service:
Component class
Export class WelcomeComponent implements OnInit {welcome: string; constructor (private userService: UserService) {} ngOnInit (): void {this.welcome = this.userService.isLoggedIn? 'Welcome,' + this.userService.user.name: 'Please log in.';}}
Mock class
Class MockUserService {isLoggedIn = true; user = {name: 'Test User'};}
test
... beforeEach (() = > {TestBed.configureTestingModule ({/ / provide the component-under-test and dependent service providers: [WelcomeComponent, {provide: UserService, useClass: MockUserService}]}); / / inject both the component and the dependent service. Comp = TestBed.get (WelcomeComponent); userService = TestBed.get (UserService);}); it ('should ask user to log in if not logged in after ngOnInit', () = > {userService.isLoggedIn = false; comp.ngOnInit (); expect (comp.welcome) .not.toContain (userService.user.name); expect (comp.welcome) .toContain (' log in');}); component DOM testing
Tests involving only classes can determine whether the behavior of the component class is normal, but not whether the component can render and interact properly.
To test the component DOM, you need to use methods such as TestBed.createComponent (). The first test is the component DOM test.
TestBed.configureTestingModule ({declarations: [BannerComponent]}); const fixture = TestBed.createComponent (BannerComponent); const component = fixture.componentInstance;expect (component) .toBeDefined ()
DispatchEvent
To simulate user input, such as entering a value for the input element, find the input element and set its value attribute. Angular does not know that you have set the value attribute of the input element. You need to call dispatchEvent () to trigger the input event of the input box, and then call detectChanges ():
It ('should convert hero name to Title Case', () = > {/ / get the name's input and display elements from the DOM const hostElement = fixture.nativeElement; const nameInput: HTMLInputElement = hostElement.querySelector (' input'); const nameDisplay: HTMLElement = hostElement.querySelector ('span'); nameInput.value =' quick BROWN fOx'; / / dispatch a DOM event so that Angular learns of input value change. NameInput.dispatchEvent (newEvent ('input')); fixture.detectChanges (); expect (nameDisplay.textContent) .tobe (' Quick Brown Fox');}); nested components
Other components are often used in components:
Dashboard Heroes About
For harmless embedded components, you can add them directly to declarations, which is the easiest way:
Describe ('AppComponent & TestModule', () = > {beforeEach (() = > {TestBed.configureTestingModule ({declarations: [AppComponent, BannerComponent, WelcomeComponent]}) .accouneComponents (). Then (() = > {fixture = TestBed.createComponent (AppComponent); comp = fixture.componentInstance;});})
You can also create some test piles for unimportant components:
@ Component ({selector: 'app-banner', template:''}) class BannerStubComponent {} @ Component ({selector: 'router-outlet', template:'}) class RouterOutletStubComponent {} @ Component ({selector: 'app-welcome', template:''}) class WelcomeStubComponent {}
Then declare them in the configuration of TestBed:
TestBed.configureTestingModule ({declarations: [AppComponent, BannerStubComponent, RouterOutletStubComponent, WelcomeStubComponent]})
Another way is to use NO_ERRORS_SCHEMA, which requires the Angular compiler to ignore elements and attributes that you don't know:
TestBed.configureTestingModule ({declarations: [AppComponent, RouterLinkDirectiveStub], schemas: [NO_ERRORS_SCHEMA]})
The NO_ERRORS_SCHEMA method is relatively simple, but don't overuse it. NO_ERRORS_SCHEMA blocks components and attributes that are missing by the compiler due to carelessness or spelling mistakes, and it can be time-consuming to find these bug manually.
RouterLinkDirectiveStub
Import {Directive, Input, HostListener} from'@ angular/core';@Directive ({selector:'[routerLink]'}) export class RouterLinkDirectiveStub {@ Input ('routerLink') linkParams: any; navigatedTo: any = null; @ HostListener (' click') onClick () {this.navigatedTo = this.linkParams;}} attribute instruction Test import {Directive, ElementRef, Input, OnChanges} from'@ angular/core' @ Directive ({selector:'[highlight]'}) / * * Set backgroundColor for the attached element to highlight color and set the element's customProperty to true * / export class HighlightDirective implements OnChanges {defaultColor = 'rgb (211111111)'; / / lightgray @ Input ('highlight') bgColor: string; constructor (private el: ElementRef) {el.nativeElement.style.customProperty = true;} ngOnChanges () {this.el.nativeElement.style.backgroundColor = this.bgColor | | this.defaultColor;}}
Attribute instructions must manipulate DOM, for example, testing for classes alone does not prove the validity of instructions. If tested by components, a single use case generally cannot explore the full capabilities of instructions. Therefore, it is better to create a man-made test component that shows all the uses of the instruction:
@ Component ({template: `Something Yellow The Default (Gray) No Highlight `}) class TestComponent {}
Test program:
BeforeEach (() = > {fixture = TestBed.configureTestingModule ({declarations: [HighlightDirective, TestComponent]}) .createComponent (TestComponent); fixture.detectChanges (); / / initial binding / / all elements with an attached HighlightDirective des = fixture.debugElement.queryAll (By.directive (HighlightDirective)); / / the h3 without the HighlightDirective bareH2 = fixture.debugElement.query (By.css ('h3:not ([highlight])');}) / color testsit ('should have three highlighted elements', () = > {expect (des.length) .tobe (3);}); it (' should color 1st background "yellow', () = > {const bgColor = des [0] .nativeElement.style.backgroundColor; expect (bgColor) .tobe ('yellow');}); it (' should color 2nd background w / default color', () = > {const dir = des [1] .promotor.get (HighlightDirective) as HighlightDirective) Const bgColor = des [1] .nativeElement.style.backgroundColor; expect (bgColor) .tobe (dir.defaultColor);}); it ('should bind background to value color', () = > {/ / easier to work with nativeElement const input = des [2] .nativeElement as HTMLInputElement; expect (input.style.backgroundColor) .tobe (' cyan', 'initial backgroundColor'); / / dispatch a DOM event so that Angular responds to the input value change. Input.value = 'green'; input.dispatchEvent (newEvent (' input')); fixture.detectChanges (); expect (input.style.backgroundColor) .tobe ('green',' changed backgroundColor');}); it ('bare should not have a customProperty', () = > {expect (bareH2.properties [' customProperty']). ToBeUndefined (); Pipe test describe ('TitleCasePipe', () = > {/ / This pipe is a pure, stateless function so no need for BeforeEach let pipe = new TitleCasePipe ()) It ('transforms "abc" to "Abc", () = > {expect (pipe.transform (' abc')). ToBe ('Abc');}); it (' transforms "abc def" to "Abc Def", () = > {expect (pipe.transform ('abc def')). ToBe (' Abc Def');}); Testing Module
RouterTestingModule
In the previous tests, we used the test pile RouterOutletStubComponent, and the tests related to Router can also use RouterTestingModule:
BeforeEach (async () = > {TestBed.configureTestingModule ({imports: [RouterTestingModule], declarations: [AppComponent],}) .compileComponents ()
RouterTestingModule can also simulate routing:
BeforeEach (() = > {TestBed.configureTestModule ({imports: [RouterTestingModule.withRoutes ([{path:', component: BlankCmp}, {path: 'simple', component: SimpleCmp}]]});})
HttpClientTestingModule
Describe ('HttpClient testing', () = > {let httpClient: HttpClient; let httpTestingController: HttpTestingController; beforeEach (()) = > {TestBed.configureTestingModule ({imports: [HttpClientTestingModule]}); / / Inject the http service and test controller for each test httpClient = TestBed.get (HttpClient); httpTestingController = TestBed.get (HttpTestingController);}); afterEach () = > {/ / After every test, assert that there are no more pending requests. HttpTestingController.verify (); it ('can test HttpClient.get', () = > {const testData: Data = {name:' Test Data'}; / / Make an HTTP GET request httpClient.get (testUrl) .subscribe (data = > / When observable resolves, result should match test data expect (data) .toEqual (testData)); / / The following `expectOne () `will match the request's URL. / / If no requests or multiple requests matched that URL / / `expectOne () `would throw. Const req = httpTestingController.expectOne ('/ data'); / / Assert that the request is a GET. Expect (req.request.method). To Equal ('GET'); / / Respond with mock data, causing Observable to resolve. / / Subscribe callback asserts that correct data was returned. Req.flush (testData); / / Finally, assert that there are no outstanding requests. HttpTestingController.verify ();});...})
On the browser test results page, clicking the "DEBUG" button opens the new tab and reruns the test program. Press "F12" to open the debugging interface, then go to Sources to find the test file (CTRL+P), and set a breakpoint in the test program to debug.
Configure the E2E test
E2E testing uses the Jasmine and Protractor testing frameworks, and Protractor is the Angular end-to-end testing framework.
Install Protractornpm I-g protractor
After installation, the node_modules\ protractor\ bin directory contains two command-line tools, protractor and webdriver-manager, where webdriver-manager is responsible for managing the driver and starting and stopping Selenium Server.
Webdriver-manager command:
Clean removes all downloaded driver files from the out_dirstart start up the selenium servershutdown shutdown the selenium serverstatus list the current available driversupdate update selected binariesversion get the current version
Update driver:
Webdriver-manager update
Chromedriver, geckodriver and selenium standalone are installed by default, the driver directory is node_modules\ protractor\ node_modules\ webdriver-manager\ selenium, and the url configuration used for download is in the webdriver-manager\ config.json file:
"cdnUrls": {"selenium": "https://selenium-release.storage.googleapis.com/"," chromedriver ":" https://chromedriver.storage.googleapis.com/", "geckodriver": "https://github.com/mozilla/geckodriver/releases/download/"," iedriver ":" https://selenium-release.storage.googleapis.com/", "androidsdk": "http://dl.google.com/android/"}"
Can be modified to another CDN:
"cdnUrls": {"selenium": "https://mirrors.huaweicloud.com/selenium/"," chromedriver ":" https://mirrors.huaweicloud.com/chromedriver/", "geckodriver": "https://mirrors.huaweicloud.com/geckodriver/"," iedriver ":" https://selenium-release.storage.googleapis.com/", "androidsdk": "http://dl.google.com/android/"}"
You can also use the parameter-- alternate_cdn:
Webdriver-manager update-alternate_cdn=... Configuration file
An App created with CLI generates an e2e project that contains the test configuration protractor.conf.js and test code.
Protractor.conf.js
Const {SpecReporter} = require ('jasmine-spec-reporter') Exports.config = {allScriptsTimeout: 11000, specs: ['. / src/**/*.e2e-spec.ts'], capabilities: {'browserName':' chrome'}, directConnect: true, baseUrl: 'http://localhost:4200/', framework:' jasmine', jasmineNodeOpts: {showColors: true, defaultTimeoutInterval: 30000, print: function () {}} OnPrepare () {require ('ts-node') .register ({project: require (' path'). Join (_ _ dirname,'. / tsconfig.e2e.json')}) Jasmine.getEnv () .addReporter (new SpecReporter ({spec: {displayStacktrace: true}));}}
By default, Protractor uses the Jasmine test framework, connects directly to the Chrome browser, and the test file extension is .e2e-spec.ts.
Browser configuration
Protractor supports browsers such as Chrome, Firefox, Safari, IE, etc.
Multiple browsers
Protractor supports launching multiple browsers at the same time, using the capabilities option in the configuration for one browser, and using multiCapabilities for multiple browsers:
MultiCapabilities: [{browserName: 'firefox'}, {browserName:' chrome'}]
In addition, you need to add configuration to package.json:
"scripts": {"webdriver-update": "webdriver-manager update"}
Update the browser driver before running the test:
Npm run webdriver-update
Otherwise, the drivers in the project will not be updated (only chrome drivers are available by default, and only global drivers are updated by running webdriver-manager update), and the following error will be reported when running the test:
No update-config.json found. Run 'webdriver-manager update' to download binaries
Browser options
Capabilities: {'browserName':' chrome', 'chromeOptions': {' args': ['show-fps-counter=true']}, capabilities: {' browserName': 'firefox',' moz:firefoxOptions': {'args': ['-- safe-mode']}}
For more options, please see the corresponding drivers ChromeDriver and GeckoDriver.
Selenium Server configuration
When using Standalone Selenium Server, you need to install JDK.
Start Selenium Server after updating driver:
Webdriver-manager updatewebdriver-manager start
Delete directConnect and baseUrl from the original configuration:
DirectConnect: true,baseUrl: 'http://localhost:4200/',
Add seleniumAddress (default is http://localhost:4444/wd/hub):
SeleniumAddress: 'http://localhost:4444/wd/hub', runs the test
Run the E2E test:
Ng e2e
Common parameters:
Base-url Base URL for protractor to connect to.--configuration (- c) A named configuration environment, as specified in the "configurations" section of angular.json.--host Host to listen on.--port The port to use to serve the application.--prod When true, sets the build configuration to the production environment.--protractor-config The name of the Protractor configuration file.--webdriver-update Try to update webdriver.
After driver is installed, if you don't update your browser, you don't have to update driver every time:
Ng e2e-- webdriver-update=false
For example, run the test times with the following error:
Events.js:167 throw er; / / Unhandled 'error' event ^ Error: read ECONNRESET at TLSWrap.onStreamRead (internal/stream_base_commons.js:111:27) Emitted' error' event
You can try to update package before testing:
Npm I npm@latest-gnpm update specified profile
If the configuration is different in different environments, different profiles can be used.
For example, enable Chrome Headless mode in a CI environment:
Create a new file called protractor-ci.conf.js under the e2e root directory as follows:
Const config = require ('. / protractor.conf'). Config;config.capabilities = {browserName: 'chrome', chromeOptions: {args: ['-headless','--no-sandbox']}}; exports.config = config
Note: the parameter disable-gpu should be added to windows system.
Run the following command test:
Ng e2e-- protractor-config=e2e\ protractor-ci.conf.js-- webdriver-update=false wrote the first E2E test import {AppPage} from'. / app.po';describe ('workspace-project App', () = > {let page: AppPage; beforeEach () = > {page = new AppPage ();}); it (' should display welcome message', () = > {page.navigateTo (); expect (page.getTitleText ()) .toEqual ('Welcome to hellographies');}) ); import {browser, by, element} from 'protractor';export class AppPage {navigateTo () {return browser.get (' /');} getTitleText () {return element (by.css ('app-root H2')). GetText ();}}
Both the E2E test and the unit test use Jasmine and the test structure is the same. Protractor provides global browser, element, and by to open pages and find elements, respectively.
Protractordescribe ('Protractor Demo App', function () {it (' should add one and two', function () {browser.get ('http://juliemr.github.io/protractor-demo/'); element (by.model (' first')) .sendKeys (1); element (by.model ('second')) .sendKeys (2); element (by.id (' gobutton')). Click (); expect (element (by.binding ('latest')). GetText (). ToEqual ('5'); / / This is wrong!});}); by.model ('first') find element ng-model= "first" by.id (' gobutton') find element by.binding ('latest') according to id find element of binding variable {{latest}}
2018 Shanghai Marathon
references
Angular Testing
Jasmine Behavior-Driven JavaScript
Karma
Protractor-end-to-end testing for Angular
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.