Kurz: Přidání testů jednotek pro projekty vizuálů Power BITutorial: Add unit tests for Power BI visual projects

Tento článek popisuje základy psaní testů jednotek pro vizuály Power BI včetně těchto postupů:This article describes the basics of writing unit tests for your Power BI visuals, including how to:

  • Nastavení Jasmine, testovacího rozhraní pro spouštěč testů Karma JavaScriptSet up the Karma JavaScript test runner testing framework, Jasmine.
  • Použití balíčku powerbi-visuals-utils-testutilsUse the powerbi-visuals-utils-testutils package.
  • Použití simulací a napodobenin ke zjednodušení testování jednotek pro vizuály Power BIUse mocks and fakes to help simplify unit testing of Power BI visuals.

PožadavkyPrerequisites

  • Nainstalovaný projekt vizuálů Power BIAn installed Power BI visuals project
  • Nakonfigurované prostředí Node.jsA configured Node.js environment

Instalace a konfigurace spouštěče testů Karma JavaScript a JasmineInstall and configure the Karma JavaScript test runner and Jasmine

Přidejte požadované knihovny do souboru package.json do oddílu devDependencies:Add the required libraries to the package.json file in the devDependencies section:

"@babel/polyfill": "^7.2.5",
"@types/d3": "5.5.0",
"@types/jasmine": "2.5.37",
"@types/jasmine-jquery": "1.5.28",
"@types/jquery": "2.0.41",
"@types/karma": "3.0.0",
"@types/lodash-es": "4.17.1",
"coveralls": "3.0.2",
"istanbul-instrumenter-loader": "^3.0.1",
"jasmine": "2.5.2",
"jasmine-core": "2.5.2",
"jasmine-jquery": "2.1.1",
"jquery": "3.1.1",
"karma": "3.1.1",
"karma-chrome-launcher": "2.2.0",
"karma-coverage": "1.1.2",
"karma-coverage-istanbul-reporter": "^2.0.4",
"karma-jasmine": "2.0.1",
"karma-junit-reporter": "^1.2.0",
"karma-sourcemap-loader": "^0.3.7",
"karma-typescript": "^3.0.13",
"karma-typescript-preprocessor": "0.4.0",
"karma-webpack": "3.0.5",
"puppeteer": "1.17.0",
"style-loader": "0.23.1",
"ts-loader": "5.3.0",
"ts-node": "7.0.1",
"tslint": "^5.12.0",
"webpack": "4.26.0"

Další informace o souboru package.json najdete v popisu v souboru npm-package.json.To learn more about package.json, see the description at npm-package.json.

Uložte soubor package.json a v umístění package.json spusťte následující příkaz:Save the package.json file and, at the package.json location, run the following command:

npm install

Správce balíčků nainstaluje všechny nové balíčky, které jsou přidané do package.json.The package manager installs all new packages that are added to package.json.

Pokud chcete spouštět testy jednotek, nakonfigurujte spouštěč testů a nástroj webpack config.To run unit tests, configure the test runner and webpack config.

Následující kód je ukázka souboru test.webpack.config.js:The following code is a sample of the test.webpack.config.js file:

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
        })
    ]
};

Následující kód je ukázka souboru karma.conf.ts:The following code is a sample of the karma.conf.ts file:

"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 Chrome to use 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"
        }
    });
};

V případě potřeby můžete tuto konfiguraci upravit.If necessary, you can modify this configuration.

Kód v karma.conf.js obsahuje následující proměnné:The code in karma.conf.js contains the following variable:

  • recursivePathToTests: Vyhledá testovací kód.recursivePathToTests: Locates the test code

  • srcRecursivePath: Vyhledá výstupní javascriptový kód po kompilaci.srcRecursivePath: Locates the output JavaScript code after compiling

  • srcCssRecursivePath: Vyhledá výstupní šablonu stylů CSS po kompilaci souboru Less se styly.srcCssRecursivePath: Locates the output CSS after compiling less file with styles

  • srcOriginalRecursivePath: Vyhledá zdrojový kód vizuálu.srcOriginalRecursivePath: Locates the source code of your visual

  • coverageFolder: Určuje, kde má být vytvořena sestava pokrytí.coverageFolder: Determines where the coverage report is to be created

Konfigurační soubor obsahuje následující vlastnosti:The configuration file includes the following properties:

  • singleRun: true: Testy se spouštějí v systému průběžné integrace, nebo je lze spustit jednorázově.singleRun: true: Tests are run on a continuous integration (CI) system, or they can be run one time. Pro ladění testů můžete změnit nastavení na false.You can change the setting to false for debugging your tests. Karma ponechá prohlížeč spuštěný, abyste mohli používat konzolu pro ladění.Karma keeps the browser running so that you can use the console for debugging.

  • files: [...]: V tomto poli můžete určit soubory, které se mají načíst do prohlížeče.files: [...]: In this array, you can specify the files to load to the browser. Obvykle to jsou zdrojové soubory, testovací případy, knihovny (Jasmine, testovací nástroje).Usually, there are source files, test cases, libraries (Jasmine, test utilities). V případě potřeby můžete do seznamu přidat další soubory.You can add additional files to the list, as necessary.

  • preprocessors: V tomto oddílu nakonfigurujete akce, které se spustí před spuštěním testů jednotek.preprocessors: In this section, you configure actions that run before the unit tests run. Předkompilují TypeScript na JavaScript, připraví soubory zdrojového mapování a vygenerují sestavu pokrytí kódu.They precompile the typescript to JavaScript, prepare source map files, and generate code coverage report. Při ladění testů můžete zakázat možnost coverage.You can disable coverage when you debug your tests. Pokrytí vygeneruje další kód pro kontrolu kódu pro pokrytí testu, což zkomplikuje testy ladění.Coverage generates additional code for check code for the test coverage, which complicates debugging tests.

Popisy všech konfigurací Karma najdete na stránce konfiguračního souboru Karma.For descriptions of all Karma configurations, go to the Karma Configuration File page.

Kvůli praktičnosti můžete přidat testovací příkaz do oddílu scripts:For your convenience, you can add a test command into scripts:

{
    "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"
    }
    ...
}

Teď jste připraveni a můžete začít psát testy jednotek.You're now ready to begin writing your unit tests.

Kontrola elementu DOM vizuáluCheck the DOM element of the visual

Pokud chcete testovat vizuál, nejprve vytvořte instanci vizuálu.To test the visual, first create an instance of visual.

Vytvoření tvůrce instance vizuáluCreate a visual instance builder

Pomocí následujícího kódu přidejte do testovací složky soubor visualBuilder.ts:Add a visualBuilder.ts file to the test folder by using the following code:

import {
    VisualBuilderBase
} from "powerbi-visuals-utils-testutils";

import {
    BarChart as VisualClass
} from "../src/visual";

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");
    }
}

Pro vytvoření instance vizuálu existuje metoda build.There's build method for creating an instance of your visual. mainElement je metoda get, která vrátí instanci kořenového elementu DOM (Document Object Model) ve vizuálu.mainElement is a get method, which returns an instance of "root" document object model (DOM) element in your visual. Metoda getter je nepovinná, ale usnadňuje psaní testů jednotek.The getter is optional, but it makes writing the unit test easier.

Teď je instance vizuálu vytvořená.You now have a build of an instance of your visual. Napišme si testovací případ.Let's write the test case. Testovací případ zkontroluje elementy SVG, které se vytvoří při zobrazení vizuálu.The test case checks the SVG elements that are created when your visual is displayed.

Vytvoření typescriptového souboru pro psaní testovacích případůCreate a typescript file to write test cases

Přidejte soubor visualTest.ts pro testovací případy pomocí následujícího kódu:Add a visualTest.ts file for the test cases by using the following code:

import powerbi from "powerbi-visuals-api";

import { BarChartBuilder } from "./VisualBuilder";

import {
    BarChart as VisualClass
} from "../src/visual";

import VisualBuilder = powerbi.extensibility.visual.test.BarChartBuilder;

describe("BarChart", () => {
    let visualBuilder: VisualBuilder;
    let dataView: DataView;

    beforeEach(() => {
        visualBuilder = new VisualBuilder(500, 500);
    });

    it("root DOM element is created", () => {
        expect(visualBuilder.mainElement).toBeInDOM();
    });
});

Volá se několik metod:Several methods are called:

  • describe: Popisuje testovací případ.describe: Describes a test case. V kontextu architektury Jasmine často popisuje sadu nebo skupinu specifikací.In the context of the Jasmine framework, it often describes a suite or group of specs.

  • beforeEach: Volá se před každým voláním metody it, která je definována v metodě describe.beforeEach: Is called before each call of the it method, which is defined in the describe method.

  • it: Definuje jednu specifikaci. Metoda it by měla obsahovat jeden nebo více objektů expectations.it: Defines a single spec. The it method should contain one or more expectations.

  • expect: Vytvoří očekávanou hodnotu pro specifikaci. Specifikace je úspěšná, pokud všechny očekávané hodnoty projdou bez chyb.expect: Creates an expectation for a spec. A spec succeeds if all expectations pass without any failures.

  • toBeInDOM: Jedna z metod matcherů.toBeInDOM: One of the matchers methods. Další informace o matcherech najdete na stránce Jasmine Namespace: matchers.For more information about matchers, see Jasmine Namespace: matchers.

Další informace o Jasmine najdete na stránce s dokumentací k architektuře Jasmine.For more information about Jasmine, see the Jasmine framework documentation page.

Spuštění testů jednotekLaunch unit tests

Tento test zkontroluje, zda se vytvořil kořenový element SVG vizuálů.This test checks that root SVG element of the visuals is created. Pokud chcete spustit test jednotek, zadejte do nástroje příkazového řádku následující příkaz:To run the unit test, enter the following command in the command-line tool:

npm run test

karma.js spustí testovací případ v prohlížeči Chrome.karma.js runs the test case in the Chrome browser.

Nástroj Karma JavaScript otevřený v prohlížeči Chrome

Poznámka

Google Chrome musí být nainstalovaný místně.You must install Google Chrome locally.

V okně příkazového řádku se zobrazí následující výstup:In the command-line window, you'll get following output:

> 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 )
================================================================================

Přidání statických dat pro testy jednotekHow to add static data for unit tests

Pomocí následujícího kódu vytvořte v testovací složce soubor visualData.ts:Create the visualData.ts file in the test folder by using the following code:

import powerbi from "powerbi-visuals-api";
import DataView = powerbi.DataView;

import {
    testDataViewBuilder,
    getRandomNumbers
} from "powerbi-visuals-utils-testutils";

export class SampleBarChartDataBuilder extends TestDataViewBuilder {
    public static CategoryColumn: string = "category";
    public static MeasureColumn: string = "measure";

    public constructor() {
        super();
        ...
    }

    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;
    }
}

Třída SampleBarChartDataBuilder rozšíří TestDataViewBuilder a implementuje abstraktní metodu getDataView.The SampleBarChartDataBuilder class extends TestDataViewBuilder and implements the abstract method getDataView.

Při umístění dat do kbelíků datových polí Power BI vytvoří kategorický objekt dataview, který bude založený na vašich datech.When you put data into data-field buckets, Power BI produces a categorical dataview object that's based on your data.

Kbelíky datových polí

V testech jednotek nemáte základní funkce Power BI pro reprodukování dat.In unit tests, you don't have Power BI core functions to reproduce the data. Musíte ale namapovat statická data ke kategorickému objektu dataview.But you need to map your static data to the categorical dataview. Jejich namapování usnadňuje třída TestDataViewBuilder.The TestDataViewBuilder class can help you map it.

Další informace o mapování zobrazení dat najdete na stránce DataViewMappings.For more information about Data View mapping, see DataViewMappings.

V metodě getDataView zavoláte metodu createCategoricalDataViewBuilder s vašimi daty.In the getDataView method, you call the createCategoricalDataViewBuilder method with your data.

V souboru capabilities.json vizuálu sampleBarChart máme objekty dataRoles a dataViewMapping:In sampleBarChart visual capabilities.json file, we have dataRoles and dataViewMapping objects:

"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"
                        }
                    }
                ]
            }
        }
    }
],

Pokud chcete vygenerovat stejné mapování, musíte nastavit následující parametry v metodě createCategoricalDataViewBuilder:To generate the same mapping, you must set the following params to createCategoricalDataViewBuilder method:

([
    {
        source: {
            displayName: "Category",
            queryName: SampleBarChartData.ColumnCategory,
            type: ValueType.fromDescriptor({ text: true }),
            roles: {
                Category: true
            },
        },
        values: this.valuesCategory
    }
],
[
    {
        source: {
            displayName: "Measure",
            isMeasure: true,
            queryName: SampleBarChartData.MeasureColumn,
            type: ValueType.fromDescriptor({ numeric: true }),
            roles: {
                Measure: true
            },
        },
        values: this.valuesMeasure
    },
], columnNames)

this.valuesCategory je pole kategorií:Where this.valuesCategory is an array of categories:

public valuesCategory: string[] = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];

this.valuesMeasure je pole měr pro jednotlivé kategorie:And this.valuesMeasure is an array of measures for each category:

public valuesMeasure: number[] = [742731.43, 162066.43, 283085.78, 300263.49, 376074.57, 814724.34, 570921.34];

Teď můžete v testu jednotek použít třídu SampleBarChartDataBuilder.Now, you can use the SampleBarChartDataBuilder class in your unit test.

Třída ValueType je definována v balíčku powerbi-visuals-utils-testutils.The ValueType class is defined in the powerbi-visuals-utils-testutils package. A metoda createCategoricalDataViewBuilder vyžaduje knihovnu lodash.And the createCategoricalDataViewBuilder method requires the lodash library.

Přidejte tyto balíčky do závislostí.Add these packages to the dependencies.

V souboru package.json v oddílu devDependenciesIn package.json at devDependencies section

"lodash-es": "4.17.1",
"powerbi-visuals-utils-testutils": "2.2.0"

zavolejteCall

npm install

a nainstalujte knihovnu lodash-es.to install lodash-es library.

Nyní můžete znovu spustit test jednotek.Now, you can run the unit test again. Musíte získat následující výstup:You must get the following output:

> 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 )
================================================================================

Vizuál se otevře v prohlížeči Chrome, jak je znázorněno níže:Your visual opens in the Chrome browser, as shown:

Spuštění UT v prohlížeči Chrome

Souhrn ukazuje, že pokrytí se zvýšilo.The summary shows that coverage has increased. Pokud chcete získat další informace o aktuálním pokrytí kódu, otevřete soubor coverage\index.html.To learn more about current code coverage, open coverage\index.html.

Index pokrytí UT

Nebo se podívejte na obor složky src:Or look at the scope of the src folder:

Pokrytí složky src

V oboru souboru můžete zobrazit zdrojový kód.In the scope of file, you can view the source code. Pokud se během testů jednotek nějaká část kódu neprovede, nástroje Coverage příslušný řádek červeně zvýrazní.The Coverage utilities would highlight the row in red if certain code isn't executed during the unit tests.

Pokrytí kódu souboru visual.ts

Důležité

Pokrytí kódu neznamená, že máte dobré pokrytí funkcí vizuálu.Code coverage doesn't mean that you have good functionality coverage of the visual. Jeden jednoduchý test jednotek poskytuje více než 96% pokrytí v src\visual.ts.One simple unit test provides over 96 percent coverage in src\visual.ts.

Další krokyNext steps

Když je vizuál připravený, můžete ho odeslat k publikování.When your visual is ready, you can submit it for publication. Další informace najdete v článku o publikování vizuálů Power BI do AppSource.For more information, see Publish Power BI visuals to AppSource.