Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makalede, Power BI görselleriniz için birim testleri yazmanın temelleri ve aşağıdakiler de açıklanmaktadır:
- Karma JavaScript test çalıştırıcısı test çerçevesi Jasmine'i ayarlayın.
- powerbi-visuals-utils-testutils paketini kullanın.
- Power BI görsellerinin birim testini basitleştirmeye yardımcı olması için moklar ve sahteleri kullanın.
Önkoşullar
- Yüklü bir Power BI görselleri projesi
- Yapılandırılmış Node.js ortamı
Bu makaledeki örneklerde test için çubuk grafiği görseli kullanılmaktadır.
Karma JavaScript test çalıştırıcısını ve Jasmine'i yükleme ve yapılandırma
gerekli kitaplıkları devDependencies bölümündeki package.json dosyasına ekleyin:
"@types/jasmine": "^5.1.5",
"@types/karma": "^6.3.9",
"coverage-istanbul-loader": "^3.0.5",
"jasmine": "^5.5.0",
"karma": "^6.4.4",
"karma-chrome-launcher": "^3.2.0",
"karma-coverage": "^2.2.1",
"karma-coverage-istanbul-reporter": "^3.0.3",
"karma-jasmine": "^5.1.0",
"karma-junit-reporter": "^2.0.1",
"karma-sourcemap-loader": "^0.4.0",
"karma-typescript": "^5.5.4",
"karma-typescript-preprocessor": "^0.4.0",
"karma-webpack": "^5.0.1",
"playwright-chromium": "^1.49.0",
"powerbi-visuals-api": "~5.11.0",
"powerbi-visuals-tools": "^5.6.0",
"powerbi-visuals-utils-testutils": "6.1.1",
"powerbi-visuals-utils-typeutils": "6.0.3",
"style-loader": "^4.0.0",
"ts-loader": "~9.5.1"
package.jsonhakkında daha fazla bilgi edinmek için npm-package.jsonkonumundaki açıklamaya bakın.
package.json dosyasını kaydedin ve package.json dosyasının konumunda aşağıdaki komutu çalıştırın:
npm install
Paket yöneticisi, package.jsoneklenen tüm yeni paketleri yükler.
Birim testlerini çalıştırmak için test çalıştırıcısını ve webpack yapılandırmasını yapılandırın.
Aşağıdaki kod, test.webpack.config.js dosyasının bir örneğidir:
const path = require('path');
const webpack = require("webpack");
module.exports = {
devtool: 'source-map',
mode: 'development',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.tsx?$/i,
enforce: 'post',
include: path.resolve(__dirname, 'src'),
exclude: /(node_modules|resources\/js\/vendor)/,
loader: 'coverage-istanbul-loader',
options: { esModules: true }
},
{
test: /\.less$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'less-loader',
options: {
lessOptions: {
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
})
]
};
Aşağıdaki kod, test.tsconfig.json dosyasının bir örneğidir:
{
"compilerOptions": {
"allowJs": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2022",
"sourceMap": true,
"outDir": "./.tmp/build/",
"sourceRoot": "../../src/",
"moduleResolution": "node",
"declaration": true,
"lib": [
"es2022",
"dom"
]
},
"files": [
"./test/visualTest.ts"
],
"include": [
"src/*.ts"
]
}
Aşağıdaki kod, karma.conf.ts dosyasının bir örneğidir:
"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("playwright-chromium").chromium.executablePath();
module.exports = (config) => {
config.set({
mode: "development",
browserNoActivityTimeout: 100000,
browsers: ["ChromeHeadless"], // or specify Chrome to use the locally installed Chrome browser
colors: true,
frameworks: ["jasmine", "webpack"],
reporters: [
"progress",
"junit",
"coverage",
"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: [
testRecursivePath,
{
pattern: srcOriginalRecursivePath,
included: false,
served: true
},
{
pattern: './capabilities.json',
watched: false,
served: true,
included: false
}
],
preprocessors: {
[testRecursivePath]: ["webpack"]
},
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: {
type: "html",
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"
}
});
};
Gerekirse bu yapılandırmayı değiştirebilirsiniz.
karma.conf.js kodu aşağıdaki değişkenleri içerir:
testRecursivePath: Test kodunu bulur.srcOriginalRecursivePath: Görselinizin kaynak kodunu bulur.coverageFolder: Kapsam raporunun oluşturulacağı yeri belirler.
Yapılandırma dosyası aşağıdaki özellikleri içerir:
singleRun: true: Testler sürekli tümleştirme (CI) sisteminde çalıştırılır veya bir kez çalıştırılabilir. Testlerinizin hatalarını ayıklamak için ayarıfalseolarak değiştirebilirsiniz. Karma çerçevesi, hata ayıklama için konsolunu kullanabilmeniz için tarayıcının çalışır durumda kalmasını sağlar.files: [...]: Bu dizide, tarayıcıya yüklenecek dosyaları belirtebilirsiniz. Yüklediğiniz dosyalar genellikle kaynak dosyalar, test çalışmaları ve kitaplıklardır (Jasmine veya test yardımcı programları gibi). Gerektiğinde daha fazla dosya ekleyebilirsiniz.preprocessors: Bu bölümde, birim testleri çalışmadan önce çalışan eylemleri yapılandıracaksınız. Eylemler TypeScript'i JavaScript'e önceden derleyebilir, kaynak eşleme dosyalarını hazırlayabilir ve bir kod kapsamı raporu oluşturabilir. Testlerinizin hatalarını ayıklarkencoveragedevre dışı bırakabilirsiniz.coverage, hata ayıklama testlerini karmaşıklaştıran kod kapsamı testi için daha fazla kod oluşturur.
Tüm Karma yapılandırmalarının açıklamaları için Karma Yapılandırma Dosyası sayfasına gidin.
Size kolaylık sağlamak için, package.jsoniçindeki scripts bir test komutu ekleyebilirsiniz:
{
"scripts": {
"pbiviz": "pbiviz",
"start": "pbiviz start",
"package": "pbiviz package",
"pretest": "pbiviz package --resources --no-minify --no-pbiviz",
"test": "karma start",
"debug": "karma start --single-run=false --browsers=Chrome"
}
...
}
Artık birim testlerinizi yazmaya başlamaya hazırsınız.
Görselin DOM öğesini denetleme
Görseli test etmek için önce görselin bir örneğini oluşturun.
Görsel örnek oluşturucu oluşturma
Aşağıdaki kodu kullanarak test klasörüne bir visualBuilder.ts dosyası ekleyin:
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(): SVGElement | null {
return this.element.querySelector("svg.barChart");
}
}
build yöntemi görselinizin bir örneğini oluşturur.
mainElement, görselinizde kök belge nesne modeli (DOM) öğesinin bir örneğini döndüren bir get yöntemidir. Getter işlevi isteğe bağlıdır, ancak birim testini yazmayı kolaylaştırır.
Artık görselinizin bir örneğini derlediniz. Test senaryosu yazalım. Örnek test çalışması, görseliniz görüntülendiğinde oluşturulan SVG öğelerini denetler.
Test çalışmalarını yazmak için TypeScript dosyası oluşturma
Aşağıdaki kodu kullanarak test çalışmaları için bir visualTest.ts dosyası ekleyin:
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(document.body.contains(visualBuilder.mainElement)).toBeTruthy();
});
});
});
Birkaç Jasmine yöntemi çağrılır:
describe: Bir test vakasını açıklar. Jasmine çerçevesi bağlamında,describegenellikle bir belirtim paketini veya grubunu açıklar.beforeEach:describeyönteminde tanımlananityönteminin her çağrısından önce çağrılır.it: Tek bir belirtim tanımlar.ityöntemi bir veya daha fazlaexpectationsiçermelidir.expect: Belirtim için bir beklenti oluşturur. Tüm beklentiler herhangi bir hata olmadan geçerse belirtim başarılı olur.toBeInDOM: eşleştiricilerinin yöntemlerinden biridir. Eşleştiriciler hakkında daha fazla bilgi için, Jasmine Ad Alanı: eşleştiricilerbölümüne bakın.
Jasmine hakkında daha fazla bilgi için Jasmine çerçevesinin dokümantasyon sayfasına bakın.
Birim testleri için statik veri ekleme
Aşağıdaki kodu kullanarak test klasöründe visualData.ts dosyasını oluşturun:
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 dataView: 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;
}
}
SampleBarChartDataBuilder sınıfı TestDataViewBuilder genişletir ve getDataViewsoyut yöntemini uygular.
Verileri veri alanı demetlerine yerleştirdiğinizde Power BI, verilerinizi temel alan kategorik bir dataview nesnesi oluşturur.
Birim testlerinde normalde verileri yeniden oluşturmak için kullandığınız Power BI çekirdek işlevlerine erişiminiz yoktur. Ancak statik verilerinizi kategorik dataviewile haritalamanız gerekir. Statik verilerinizi eşlemek için TestDataViewBuilder sınıfını kullanın.
Veri Görünümü eşlemesi hakkında daha fazla bilgi için bkz. DataViewMappings.
getDataView yönteminde verilerinizle createCategoricalDataViewBuilder yöntemini çağırırsınız.
sampleBarChart görsel capabilities.json dosyasında dataRoles ve dataViewMapping nesneleri vardır:
"dataRoles": [
{
"displayName": "Category Data",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Measure Data",
"name": "measure",
"kind": "Measure"
},
{
"displayName": "Tooltips",
"name": "Tooltips",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"conditions": [
{
"category": {
"max": 1
},
"measure": {
"max": 1
}
}
],
"categorical": {
"categories": {
"for": {
"in": "category"
}
},
"values": {
"select": [
{
"bind": {
"to": "measure"
}
}
]
}
}
}
],
Aynı eşlemeyi oluşturmak için aşağıdaki parametreleri createCategoricalDataViewBuilder yöntemine ayarlamanız gerekir:
([
{
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)
burada this.valuesCategory bir kategori dizisidir:
public valuesCategory: string[] = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
this.valuesMeasure her kategori için bir ölçü dizisidir:
public valuesMeasure: number[] = [742731.43, 162066.43, 283085.78, 300263.49, 376074.57, 814724.34, 570921.34];
visualData.ts son sürümü aşağıdaki kodu içerir:
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;
}
}
ValueType sınıfı powerbi-visuals-utils-typeutils paketinde tanımlanır.
Şimdi birim testini çalıştırabilirsiniz.
Birim testlerini başlatma
Bu test, görsel çalıştırıldığında görselinizin kök SVG öğesinin mevcut olup olmadığını denetler. Birim testini çalıştırmak için komut satırı aracına aşağıdaki komutu girin:
npm run test
karma.js Test çalışmasını Chrome tarayıcısında çalıştırır.
Not
Google Chrome'u yerel olarak yüklemeniz gerekir.
Komut satırı penceresinde aşağıdaki çıkışı alırsınız:
> karma start
Webpack bundling...
assets by status 8.31 KiB [compared for emit]
assets by path ../build/test/*.ts 1020 bytes
asset ../build/test/visualData.d.ts 512 bytes [compared for emit]
asset ../build/test/visualBuilder.d.ts 499 bytes [compared for emit]
asset ../build/test/visualTest.d.ts 11 bytes [compared for emit]
assets by path ../build/src/*.ts 6.67 KiB
asset ../build/src/barChart.d.ts 4.49 KiB [compared for emit]
asset ../build/src/barChartSettingsModel.d.ts 2.18 KiB [compared for emit]
asset visualTest.3941401795.js 662 bytes [compared for emit] (name: visualTest.3941401795) 1 related asset
assets by status 2.48 MiB [emitted]
asset commons.js 2.48 MiB [emitted] (name: commons) (id hint: commons) 1 related asset
asset runtime.js 6.48 KiB [emitted] (name: runtime) 1 related asset
Entrypoint visualTest.3941401795 2.48 MiB (2.34 MiB) = runtime.js 6.48 KiB commons.js 2.48 MiB visualTest.3941401795.js 662 bytes 3 auxiliary assets
webpack 5.97.0 compiled successfully in 3847 ms
04 12 2024 11:01:19.255:INFO [karma-server]: Karma v6.4.4 server started at http://localhost:9876/
04 12 2024 11:01:19.257:INFO [launcher]: Launching browsers ChromeHeadless with concurrency unlimited
04 12 2024 11:01:19.277:INFO [launcher]: Starting browser ChromeHeadless
04 12 2024 11:01:20.634:INFO [Chrome Headless 131.0.0.0 (Windows 10)]: Connected on socket QYSj9NyHQ14QjFBoAAAB with id 9616879
Chrome Headless 131.0.0.0 (Windows 10): Executed 1 of 1 SUCCESS (0.016 secs / 0.025 secs)
TOTAL: 1 SUCCESS
TOTAL: 1 SUCCESS
=============================== Coverage summary ===============================
Statements : 66.07% ( 187/283 )
Branches : 34.88% ( 45/129 )
Functions : 52.85% ( 37/70 )
Lines : 65.83% ( 185/281 )
================================================================================
Geçerli kod kapsamı hakkında daha fazla bilgi edinmek için coverage/html-report/index.html dosyasını açın.
Dosya kapsamında kaynak kodu görüntüleyebilirsiniz. birim testleri sırasında belirli kod satırları çalışmazsa coverage yardımcı programları satırı kırmızıyla vurgular.
Önemli
Kod kapsamı, görselin iyi işlevsellik kapsamına sahip olduğunuz anlamına gelmez. Basit bir birim testi, src/barChart.ts'da yüzde 96'nın üzerinde coverage sağlar.
Hata ayıklama
Tarayıcı konsolu aracılığıyla testlerinizin hatalarını ayıklamak için karma.conf.ts içindeki singleRun değerini falseolarak değiştirin. Bu ayar, testler çalıştırıldıktan sonra tarayıcı başlatıldığında tarayıcınızı çalışır durumda tutar.
Görseliniz Chrome tarayıcısında açılır.
İlgili içerik
Görseliniz hazır olduğunda yayına gönderebilirsiniz. Daha fazla bilgi için bkz. Power BI görsellerini AppSourceyayımlama.