Opplæring: Legge til enhetstester for visualobjektprosjekter i Power BI
Denne artikkelen beskriver det grunnleggende om å skrive enhetstester for Power BI-visualobjektene, inkludert hvordan du gjør følgende:
- Konfigurer Testing-rammeverket for JavaScript-testløper for Karma, Jasmine.
- Bruk powerbi-visuals-utils-testutils-pakken.
- Bruk mocks og fakes for å forenkle enhetstesting av Power BI-visualobjekter.
Forutsetning
- Et installert Power BI visualobjektprosjekt
- Et konfigurert Node.js-miljø
Eksemplene i denne artikkelen bruker stolpediagrammet for testing.
Installere og konfigurere Karma JavaScript-testløperen og Jasmine
Legg til de nødvendige bibliotekene i package.json-filen i devDependencies
delen:
"@types/d3": "5.7.2",
"@types/d3-selection": "^1.0.0",
"@types/jasmine": "^3.10.2",
"@types/jasmine-jquery": "^1.5.34",
"@types/jquery": "^3.5.8",
"@types/karma": "^6.3.1",
"@types/lodash-es": "^4.17.5",
"coveralls": "^3.1.1",
"d3": "5.12.0",
"jasmine": "^3.10.0",
"jasmine-core": "^3.10.1",
"jasmine-jquery": "^2.1.1",
"jquery": "^3.6.0",
"karma": "^6.3.9",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage": "^2.0.3",
"karma-coverage-istanbul-reporter": "^3.0.3",
"karma-jasmine": "^4.0.1",
"karma-junit-reporter": "^2.0.1",
"karma-sourcemap-loader": "^0.3.8",
"karma-typescript": "^5.5.2",
"karma-typescript-preprocessor": "^0.4.0",
"karma-webpack": "^5.0.0",
"powerbi-visuals-api": "^3.8.4",
"powerbi-visuals-tools": "^3.3.2",
"powerbi-visuals-utils-dataviewutils": "^2.4.1",
"powerbi-visuals-utils-formattingutils": "^4.7.1",
"powerbi-visuals-utils-interactivityutils": "^5.7.1",
"powerbi-visuals-utils-tooltiputils": "^2.5.2",
"puppeteer": "^11.0.0",
"style-loader": "^3.3.1",
"ts-loader": "~8.2.0",
"ts-node": "^10.4.0",
"tslint": "^5.20.1",
"tslint-microsoft-contrib": "^6.2.0"
Hvis du vil ha mer informasjon om package.json, kan du se beskrivelsen på npm-package.json.
Lagre package.json-filen, og kjør følgende kommando på plasseringen til package.json-filen:
npm install
Pakkebehandling installerer alle nye pakker som legges til package.json.
Hvis du vil kjøre enhetstester, konfigurerer du testløperen og konfigurasjonen webpack
.
Følgende kode er et eksempel på filen test.webpack.config.js :
const path = require('path');
const webpack = require("webpack");
module.exports = {
devtool: 'source-map',
mode: 'development',
optimization : {
concatenateModules: false,
minimize: false
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.tsx?$/i,
enforce: 'post',
include: /(src)/,
exclude: /(node_modules|resources\/js\/vendor)/,
loader: 'istanbul-instrumenter-loader',
options: { esModules: true }
},
{
test: /\.less$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'less-loader',
options: {
paths: [path.resolve(__dirname, 'node_modules')]
}
}
]
}
]
},
externals: {
"powerbi-visuals-api": '{}'
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.css']
},
output: {
path: path.resolve(__dirname, ".tmp/test")
},
plugins: [
new webpack.ProvidePlugin({
'powerbi-visuals-api': null
})
]
};
Følgende kode er et eksempel på karma.conf.ts-filen :
"use strict";
const webpackConfig = require("./test.webpack.config.js");
const tsconfig = require("./test.tsconfig.json");
const path = require("path");
const testRecursivePath = "test/visualTest.ts";
const srcOriginalRecursivePath = "src/**/*.ts";
const coverageFolder = "coverage";
process.env.CHROME_BIN = require("puppeteer").executablePath();
import { Config, ConfigOptions } from "karma";
module.exports = (config: Config) => {
config.set(<ConfigOptions>{
mode: "development",
browserNoActivityTimeout: 100000,
browsers: ["ChromeHeadless"], // or specify Chrome to use the locally installed Chrome browser
colors: true,
frameworks: ["jasmine"],
reporters: [
"progress",
"junit",
"coverage-istanbul"
],
junitReporter: {
outputDir: path.join(__dirname, coverageFolder),
outputFile: "TESTS-report.xml",
useBrowserName: false
},
singleRun: true,
plugins: [
"karma-coverage",
"karma-typescript",
"karma-webpack",
"karma-jasmine",
"karma-sourcemap-loader",
"karma-chrome-launcher",
"karma-junit-reporter",
"karma-coverage-istanbul-reporter"
],
files: [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/jasmine-jquery/lib/jasmine-jquery.js",
{
pattern: './capabilities.json',
watched: false,
served: true,
included: false
},
testRecursivePath,
{
pattern: srcOriginalRecursivePath,
included: false,
served: true
}
],
preprocessors: {
[testRecursivePath]: ["webpack", "coverage"]
},
typescriptPreprocessor: {
options: tsconfig.compilerOptions
},
coverageIstanbulReporter: {
reports: ["html", "lcovonly", "text-summary", "cobertura"],
dir: path.join(__dirname, coverageFolder),
'report-config': {
html: {
subdir: 'html-report'
}
},
combineBrowserReports: true,
fixWebpackSourcePaths: true,
verbose: false
},
coverageReporter: {
dir: path.join(__dirname, coverageFolder),
reporters: [
// reporters not supporting the `file` property
{ type: 'html', subdir: 'html-report' },
{ type: 'lcov', subdir: 'lcov' },
// reporters supporting the `file` property, use `subdir` to directly
// output them in the `dir` directory
{ type: 'cobertura', subdir: '.', file: 'cobertura-coverage.xml' },
{ type: 'lcovonly', subdir: '.', file: 'report-lcovonly.txt' },
{ type: 'text-summary', subdir: '.', file: 'text-summary.txt' },
]
},
mime: {
"text/x-typescript": ["ts", "tsx"]
},
webpack: webpackConfig,
webpackMiddleware: {
stats: "errors-only"
}
});
};
Hvis det er nødvendig, kan du endre denne konfigurasjonen.
Koden i karma.conf.js inneholder følgende variabler:
recursivePathToTests
: Finner testkoden.srcRecursivePath
: Finner JavaScript-koden for utdata etter kompilering.srcCssRecursivePath
: Finner utdata-CSS etter kompilering av mindre fil med stiler.srcOriginalRecursivePath
: Finner kildekoden for visualobjektet.coverageFolder
: Bestemmer hvor dekningsrapporten skal opprettes.
Konfigurasjonsfilen inneholder følgende egenskaper:
singleRun: true
: Tester kjøres på et system for kontinuerlig integrering (CI), eller de kan kjøres én gang. Du kan endre innstillingen til feilsøkingfalse
av testene. Karma-rammeverket holder nettleseren i gang, slik at du kan bruke konsollen til feilsøking.files: [...]
: I denne matrisen kan du angi filene som skal lastes inn i nettleseren. Filene du laster inn, er vanligvis kildefiler, testtilfeller og biblioteker (for eksempel Jasmine eller testverktøy). Du kan legge til flere filer etter behov.preprocessors
: I denne delen konfigurerer du handlinger som kjører før enhetstestene kjøres. Handlingene kan forhåndskompilere TypeScript til JavaScript, klargjøre kildetilordningsfiler og generere en kodedekningsrapport. Du kan deaktiverecoverage
når du feilsøker testene.coverage
genererer mer kode for kodedekningstesting, noe som kompliserer feilsøkingstester.
Hvis du vil ha beskrivelser av alle Karma-konfigurasjoner, kan du gå til siden Karma Configuration File .
For enkelhets skyld kan du legge til en testkommando scripts
i package.json:
{
"scripts": {
"pbiviz": "pbiviz",
"start": "pbiviz start",
"typings":"node node_modules/typings/dist/bin.js i",
"lint": "tslint -r \"node_modules/tslint-microsoft-contrib\" \"+(src|test)/**/*.ts\"",
"pretest": "pbiviz package --resources --no-minify --no-pbiviz --no-plugin",
"test": "karma start"
}
...
}
Nå er du klar til å begynne å skrive enhetstestene.
Kontrollere DOM-elementet i visualobjektet
Hvis du vil teste visualobjektet, må du først opprette en forekomst av visualobjektet.
Opprette et visualobjektforekomstverktøy
Legg til en visualBuilder.ts-fil i testmappen ved hjelp av følgende kode:
import { VisualBuilderBase } from "powerbi-visuals-utils-testutils";
import { BarChart as VisualClass } from "../src/barChart";
import powerbi from "powerbi-visuals-api";
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
export class BarChartBuilder extends VisualBuilderBase<VisualClass> {
constructor(width: number, height: number) {
super(width, height);
}
protected build(options: VisualConstructorOptions) {
return new VisualClass(options);
}
public get mainElement() {
return $(this.element).children("svg.barChart");
}
}
Metoden build
oppretter en forekomst av visualobjektet. mainElement
er en hent-metode som returnerer en forekomst av et DOM-element (root document object model) i visualobjektet. Getter er valgfritt, men det gjør det enklere å skrive enhetstesten.
Du har nå en bygg av en forekomst av visualobjektet. La oss skrive testtilfellet. Eksempeltesttilfellet kontrollerer SVG-elementene som opprettes når visualobjektet vises.
Opprette en TypeScript-fil for å skrive testtilfeller
Legg til en visualTest.ts-fil for testtilfellene ved hjelp av følgende kode:
import powerbi from "powerbi-visuals-api";
import { BarChartBuilder } from "./visualBuilder";
import { SampleBarChartDataBuilder } from "./visualData";
import DataView = powerbi.DataView;
describe("BarChart", () => {
let visualBuilder: BarChartBuilder;
let dataView: DataView;
let defaultDataViewBuilder: SampleBarChartDataBuilder;
beforeEach(() => {
visualBuilder = new BarChartBuilder(500, 500);
defaultDataViewBuilder = new SampleBarChartDataBuilder();
dataView = defaultDataViewBuilder.getDataView();
});
it("root DOM element is created", () => {
visualBuilder.updateRenderTimeout(dataView, () => {
expect(visualBuilder.mainElement[0]).toBeInDOM();
});
});
});
Flere Jasmine-metoder kalles:
describe
: Beskriver et testtilfelle. I sammenheng med Jasmine-rammeverketdescribe
beskriver du ofte en serie eller en gruppe spesifikasjoner.beforeEach
: Kalles for hvert kall avit
metoden, som er definert idescribe
metoden.it
: Definerer én enkelt spesifikasjon. Metodenit
må inneholde én eller flereexpectations
.expect
: Oppretter en forventning for en spesifikasjon. En spesifikasjon lykkes hvis alle forventninger passerer uten feil.toBeInDOM
: Er én av matchers-metodene . Hvis du vil ha mer informasjon om matchers, kan du se Jasmine Namespace: matchers.
Hvis du vil ha mer informasjon om Jasmine, kan du se dokumentasjonssiden for Jasmine Framework.
Start enhetstester
Denne testen kontrollerer at det primære SVG-elementet for visualobjektet finnes når visualobjektet kjøres. Hvis du vil kjøre enhetstesten, skriver du inn følgende kommando i kommandolinjeverktøyet:
npm run test
karma.js
kjører testtilfellet i Chrome-nettleseren.
Merk
Du må installere Google Chrome lokalt.
I kommandolinjevinduet får du følgende utdata:
> karma start
23 05 2017 12:24:26.842:WARN [watcher]: Pattern "E:/WORKSPACE/PowerBI/PowerBI-visuals-sampleBarChart/data/*.csv" does not match any file.
23 05 2017 12:24:30.836:WARN [karma]: No captured browser, open https://localhost:9876/
23 05 2017 12:24:30.849:INFO [karma]: Karma v1.3.0 server started at https://localhost:9876/
23 05 2017 12:24:30.850:INFO [launcher]: Launching browser Chrome with unlimited concurrency
23 05 2017 12:24:31.059:INFO [launcher]: Starting browser Chrome
23 05 2017 12:24:33.160:INFO [Chrome 58.0.3029 (Windows 10 0.0.0)]: Connected on socket /#2meR6hjXFmsE_fjiAAAA with id 5875251
Chrome 58.0.3029 (Windows 10 0.0.0): Executed 1 of 1 SUCCESS (0.194 secs / 0.011 secs)
=============================== Coverage summary ===============================
Statements : 27.43% ( 65/237 )
Branches : 19.84% ( 25/126 )
Functions : 43.86% ( 25/57 )
Lines : 20.85% ( 44/211 )
================================================================================
Slik legger du til statiske data for enhetstester
Opprett visualData.ts-filen i testmappen ved hjelp av følgende kode:
import powerbi from "powerbi-visuals-api";
import DataView = powerbi.DataView;
import { testDataViewBuilder } from "powerbi-visuals-utils-testutils";
import TestDataViewBuilder = testDataViewBuilder.TestDataViewBuilder;
export class SampleBarChartDataBuilder extends TestDataViewBuilder {
public static CategoryColumn: string = "category";
public static MeasureColumn: string = "measure";
public getDataView(columnNames?: string[]): DataView {
let dateView: any = this.createCategoricalDataViewBuilder(
[
...
],
[
...
],
columnNames
).build();
// there's client side computed maxValue
let maxLocal = 0;
this.valuesMeasure.forEach((item) => {
if (item > maxLocal) {
maxLocal = item;
}
});
(<any>dataView).categorical.values[0].maxLocal = maxLocal;
return dataView;
}
}
Klassen SampleBarChartDataBuilder
utvider TestDataViewBuilder
og implementerer den abstrakte metoden getDataView
.
Når du plasserer data i datafeltsamlinger, produserer Power BI et kategorisk dataview
objekt som er basert på dataene dine.
I enhetstester har du ikke tilgang til Power BI-kjernefunksjoner som du vanligvis bruker til å reprodusere dataene. Du må imidlertid tilordne statiske data til den kategoriske dataview
. TestDataViewBuilder
Bruk klassen til å tilordne statiske data.
Hvis du vil ha mer informasjon om datavisningstilordning, kan du se DataViewMappings.
getDataView
I metoden kaller createCategoricalDataViewBuilder
du metoden med dataene.
sampleBarChart
I visualobjekt-capabilities.json-filen har dataRoles
vi og dataViewMapping
objekter:
"dataRoles": [
{
"displayName": "Category Data",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Measure Data",
"name": "measure",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"conditions": [
{
"category": {
"max": 1
},
"measure": {
"max": 1
}
}
],
"categorical": {
"categories": {
"for": {
"in": "category"
}
},
"values": {
"select": [
{
"bind": {
"to": "measure"
}
}
]
}
}
}
],
Hvis du vil generere samme tilordning, må du angi følgende parametere til createCategoricalDataViewBuilder
metoden:
([
{
source: {
displayName: "Category",
queryName: SampleBarChartDataBuilder.CategoryColumn,
type: ValueType.fromDescriptor({ text: true }),
roles: {
Category: true
},
},
values: this.valuesCategory
}
],
[
{
source: {
displayName: "Measure",
isMeasure: true,
queryName: SampleBarChartDataBuilder.MeasureColumn,
type: ValueType.fromDescriptor({ numeric: true }),
roles: {
Measure: true
},
},
values: this.valuesMeasure
},
], columnNames)
Hvor this.valuesCategory
er en matrise med kategorier:
public valuesCategory: string[] = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
Og this.valuesMeasure
er en matrise med mål for hver kategori:
public valuesMeasure: number[] = [742731.43, 162066.43, 283085.78, 300263.49, 376074.57, 814724.34, 570921.34];
Den endelige versjonen av visualData.ts inneholder følgende kode:
import powerbi from "powerbi-visuals-api";
import DataView = powerbi.DataView;
import { testDataViewBuilder } from "powerbi-visuals-utils-testutils";
import { valueType } from "powerbi-visuals-utils-typeutils";
import ValueType = valueType.ValueType;
import TestDataViewBuilder = testDataViewBuilder.TestDataViewBuilder;
export class SampleBarChartDataBuilder extends TestDataViewBuilder {
public static CategoryColumn: string = "category";
public static MeasureColumn: string = "measure";
public valuesCategory: string[] = [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday",
];
public valuesMeasure: number[] = [
742731.43, 162066.43, 283085.78, 300263.49, 376074.57, 814724.34, 570921.34,
];
public getDataView(columnNames?: string[]): DataView {
let dataView: any = this.createCategoricalDataViewBuilder(
[
{
source: {
displayName: "Category",
queryName: SampleBarChartDataBuilder.CategoryColumn,
type: ValueType.fromDescriptor({ text: true }),
roles: {
category: true,
},
},
values: this.valuesCategory,
},
],
[
{
source: {
displayName: "Measure",
isMeasure: true,
queryName: SampleBarChartDataBuilder.MeasureColumn,
type: ValueType.fromDescriptor({ numeric: true }),
roles: {
measure: true,
},
},
values: this.valuesMeasure,
},
],
columnNames
).build();
// there's client side computed maxValue
let maxLocal = 0;
this.valuesMeasure.forEach((item) => {
if (item > maxLocal) {
maxLocal = item;
}
});
(<any>dataView).categorical.values[0].maxLocal = maxLocal;
return dataView;
}
}
Nå kan du bruke SampleBarChartDataBuilder
klassen i enhetstesten.
Klassen ValueType
er definert i powerbi-visuals-utils-testutils-pakken.
Legg til powerbi-visuals-utils-testutils-pakken i avhengighetene. Finn inndelingen package.json
dependencies
i filen, og legg til følgende kode:
"powerbi-visuals-utils-testutils": "^2.4.1",
Ring
npm install
for å installere powerbi-visuals-utils-testutils
pakken.
Nå kan du kjøre enhetstesten på nytt. Du må få følgende utdata:
> karma start
23 05 2017 16:19:54.318:WARN [watcher]: Pattern "E:/WORKSPACE/PowerBI/PowerBI-visuals-sampleBarChart/data/*.csv" does not match any file.
23 05 2017 16:19:58.333:WARN [karma]: No captured browser, open https://localhost:9876/
23 05 2017 16:19:58.346:INFO [karma]: Karma v1.3.0 server started at https://localhost:9876/
23 05 2017 16:19:58.346:INFO [launcher]: Launching browser Chrome with unlimited concurrency
23 05 2017 16:19:58.394:INFO [launcher]: Starting browser Chrome
23 05 2017 16:19:59.873:INFO [Chrome 58.0.3029 (Windows 10 0.0.0)]: Connected on socket /#NcNTAGH9hWfGMCuEAAAA with id 3551106
Chrome 58.0.3029 (Windows 10 0.0.0): Executed 1 of 1 SUCCESS (1.266 secs / 1.052 secs)
=============================== Coverage summary ===============================
Statements : 56.72% ( 135/238 )
Branches : 32.54% ( 41/126 )
Functions : 66.67% ( 38/57 )
Lines : 52.83% ( 112/212 )
================================================================================
Sammendraget viser at dekningen har økt. Hvis du vil lære mer om gjeldende kodedekning, åpner coverage/html-report/index.html
du filen.
Eller se på omfanget av src
mappen:
I filomfanget kan du vise kildekoden. Verktøyene coverage
uthever raden i rødt hvis bestemte linjer med kode ikke kjører under enhetstestene.
Viktig
Kodedekning betyr ikke at du har god funksjonalitetsdekning for visualobjektet. En enkel enhetstest gir over 96 prosent dekning i src/barChart.ts
.
Feilsøking
Hvis du vil feilsøke testene via nettleserkonsollen singleRun
, endrer du verdien i karma.conf.ts til false
. Denne innstillingen vil holde nettleseren i gang når nettleseren starter etter at testene kjøres.
Visualobjektet åpnes i Chrome-nettleseren.
Relatert innhold
Når visualobjektet er klart, kan du sende det inn for publisering. Hvis du vil ha mer informasjon, kan du se Publisere Power BI-visualobjekter til AppSource.
Tilbakemeldinger
https://aka.ms/ContentUserFeedback.
Kommer snart: Gjennom 2024 faser vi ut GitHub Issues som tilbakemeldingsmekanisme for innhold, og erstatter det med et nytt system for tilbakemeldinger. Hvis du vil ha mer informasjon, kan du se:Send inn og vis tilbakemelding for