以前、企業ブログを持っていなかったとき、Microsoft TFS(構内のVisual Studio Team Servives)を使用してソフトウェア開発ライフサイクルを管理し、テストを自動化する方法について書きました。 特に、私たちは毎日実行する1つのパッケージにさまざまなシステムでの自動テストの大規模なセットをまとめました。 これについては、DevOpsDaysMoscowカンファレンス( プレゼンテーション 、 ビデオプレゼンテーション )で詳しく説明しました。 実装中に、いくつかの問題が発生しました。
- 単一のスレッドで自動テストを連続して実行すると時間がかかりすぎる
- 一部の自動テストのクラッシュは記録されません
JenkinsビルドはVSTSでテスト結果を公開しません
これらの問題はすべて、ネイティブVSTS拡張機能を使用して正常に解決されました。
- 並列アセンブリ
- 自動欠陥
標準Jenkinsジョブ起動タスクの改良
問題の詳細と解決策の探し方については、前回の記事で説明します。 今日は、これらの拡張機能を作成する方法と、拡張機能の開発者を支援する方法についてお話したいと思います。
どうやって?
ほぼ最初から、問題を解決する最も簡単な方法は、TFSで自分のタスクまたはビルドステップを使用することであることに気付きました。 タスクは、powershellまたはtypescriptで記述できます。 タイプスクリプトを選択しました。そのため、実際にはjavascriptですが、タイピングがサポートされています。 Habrを含む、typescriptの利点とその使用に関する多くの記事があります。 私たちにとって、主な利点は次のとおりです。
- IntelliSenseおよび静的チェック
- Linuxエージェントを搭載
- npmモジュールを使用する機能。 これは、車輪を再発明する必要がないことを意味します-UUIDの生成が必要です-それは、Visual Studio形式(trxファイル)でのテスト結果の生成です-つまり、XMLでの作業もあります。
- 言語レベルの非同期サポート-async / await。 コールバック地獄を取り除くことができます。 非同期のメソッドと呼び出しは、同期のように見えます。
TFSを使用するために、Microsoftは2つのnpmモジュールを作成して公開しました。これにより、車輪を再発明する必要がなくなりました。
また、Microsoftの多くのタスクが書かれ、タイプスクリプトが作成され、オープンライセンスの下で公開されていることも大きな助けになりました。 サンプルとして使用できることに加えて、このリポジトリの独自のフォークを作成し、タスクをすばやく作成し、拡張機能のアセンブリとパッケージ化を自動化するための独自のブートストラップキットを作成することができました。
なに?
VSTSの課題は何ですか? これは必須コンポーネントのセットです。
- タスク定義
- メインタスクスクリプト
- package.json-依存関係の定義
タスクアイコン
タスク定義
タスク定義には複数のブロックが含まれます。
識別ブロック:
{ "id": "b5525419-bae1-44de-a479-d6de6a3ccb2f", "name": "TestTask", "friendlyName": "TestTask", "description": "TestTask", "helpMarkDown": "", "category": "Build", "author": "authorName", "version": { "Major": 1, "Minor": 0, "Patch": 0 }, "instanceNameFormat": "TestTask $(testparam)" }
このブロックは、タスクの一意のID、名前、カテゴリ、バージョンを記述します。 タスクを作成するとき、これらのフィールドをすべて指定する必要があります。 instanceNameFormatフィールドは、デフォルトのVSTSアセンブリでタスクの名前がどのように見えるかを決定します。 パラメーターブロックのパラメーターを$(パラメーター名)の形式で含めることができます
パラメータブロック
パラメーターブロックは、タスクの入力パラメーター、その名前、説明、およびタイプを示します。 タスク設定ページで表示しやすいように、パラメーターをグループ化できます。 次のブロックはAutoDefectsタスクパラメーターです。
{ "groups": [ { "name": "authentication", "displayName": "Authentication", "isExpanded": false } ], "inputs": [ { "name": "Assignees", "type": "filePath", "label": "Assignees list file", "defaultValue": "assignees.json", "required": false, "helpMarkDown": "Bug assignees list in json format. Format: {\"testrunname\":\"username\"}" }, { "name": "authtype", "type": "pickList", "label": "Authentication type", "defaultValue": "oauth", "required": false, "helpMarkDown": "Authentication type to access the tfs rest api", "options": { "oauth": "OAuth", "NTLM": "NTLM", "Basic": "Basic" }, "groupName" : "authentication" }, { "name": "Username", "type": "string", "label": "Username", "defaultValue": "", "required": false, "helpMarkDown": "Username to access tfs rest api (NTLM and Basic types)", "groupName" : "authentication", "visibilityRule" : "authtype != OAuth" }, { "name": "Password", "type": "string", "label": "Password", "defaultValue": "", "required": false, "helpMarkDown": "Password to access tfs rest api (NTLM and Basic types)", "groupName" : "authentication", "visibilityRule" : "authtype != OAuth" } ] }
認証スキームを決定するパラメーターは、デフォルトでは折りたたまれている別のグループに配置されます。
最も一般的に使用されるパラメーターのタイプは次のとおりです。
- stringは通常の文字列です。
- pickList-値のリストが制限された選択ボックス
- filePath-アセンブリリポジトリ内のファイルを選択します。
実行単位
タスクのメインの実行可能ファイルへのリンクが含まれています
{ "execution": { "Node": { "target": "testtask.ts" } } }
ローカリゼーションユニット
{ "messages": { "taskSucceeded": "All done", "taskFailed": "Task Failed" } }
ビルドログファイルにタスクを記録するためのローカライズされた行のセットが含まれています。 上記のブロックよりも使用頻度が低い。 現在のローカル設定のメッセージは、task.loc( "messagename")を呼び出すことで受信できます。
メイン実行ファイル
メインの実行可能ファイルは、タスクの開始時にVSTSを実行するスクリプトです。 少なくとも、タスクの機能とエラー処理に必要なモジュールをインポートするためのコードが含まれている必要があります。 例:
import tl = require('vsts-task-lib/task'); import trm = require('vsts-task-lib/toolrunner'); import path = require('path'); import fs = require('fs'); import Q = require("q"); import * as vm from 'vso-node-api'; import * as bi from 'vso-node-api/interfaces/BuildInterfaces'; import * as ci from 'vso-node-api/interfaces/CoreInterfaces'; import * as ti from 'vso-node-api/interfaces/TestInterfaces'; import * as wi from 'vso-node-api/interfaces/WorkItemTrackingInterfaces'; async function run() { tl.setResourcePath(path.join(__dirname, 'task.json')); let projId = tl.getVariable("System.TeamProjectId"); try { } catch(err) { console.log(err); console.log(err.stack); throw err; } } run() .then(r => tl.setResult(tl.TaskResult.Succeeded,tl.loc("taskSucceeded"))) .catch(r => tl.setResult(tl.TaskResult.Failed,tl.loc("taskFailed")))
ご覧のとおり、タスクはタスクごとにほとんど変化しない標準コンポーネントのセットです。 したがって、3番目のタスクを作成したときに、タスクの作成を自動化するというアイデアが浮上しました。 そのため、VSTSの拡張機能の開発を大幅に促進するブートストラップがありました。
どれくらい速い?
VSTSのタスクを作成するとき、タスク自体のコードを書く以外に何をする必要がありますか? 通常、手順は同じです。
- タスクスケルトンを作成する
- 分離されたコンポーネントにタスクを組み立てる
- VSTSに公開するためのvsixでのタスクのパック
これらの手順はすべて自動化して開発をスピードアップし、不必要な手作業を排除できます。 これらの手順を自動化するには、ブートストラップを使用できます。 コレクターのワークフローは、Microsoftのタスクコレクターに似ています。アセンブリのタスクは、プロジェクトのルートにあるmake-options.jsonファイルにリストされています。
{ "tasks": [ "AutoDefects", "ChainBuildsAwaiter", "ChainBuildsStarter", "TestTask" ], ... }
前提条件
拡張機能を作成するには、次のソフトウェアが必要です。
- ローカルJavaScriptマシン-nodejs
npm install -g typescript
インタープリターnpm install -g typescript
- Gulpコレクター
npm install -g gulp
- VSTS tfx-cliコンソールユーティリティ
npm install -g tfx-cli
タスク作成
TaskNameタスクは次のコマンドで作成されます:
gulp generate –-name TaskName
コマンドの実行の結果、次のことが発生します。
- タスクは、アセンブリのタスクのプロジェクトリストに追加されます。
- タスクディレクトリとスケルトンファイルの作成-taskname .ts、task.json、package.json、typings.json、icon.png
骨格ファイルには、最低限必要なデータとコードのセットが含まれています。
プロジェクトタスクの組み立て
プロジェクトのタスクのアセンブリは、 gulp
によって実行されます
この場合、 make-options.jsonにリストされているすべてのタスクについて、次のことが発生します。
- .jsへの.tsのブロードキャスト
- node_modulesをタスクディレクトリに設定する
- 言語ファイルの生成
タスクのパッケージ化
パッキングタスクは、 gulp mkext [--all] [--exts ext1,ext2]
デフォルトでは、各タスクは個別のvsixファイルにパックされます。--allオプションが指定されている場合、すべてのタスクは1つの大きなvsixファイルに収集されます。
デフォルトでは、 make-options.jsonにリストされているすべてのタスクがパックされています。--extsオプションが指定されている場合、extensionパラメーターにリストされているタスクのみがパックされます。
私たちは開いています
GitHubで公開されているブートストラップ-フォーク、機能リクエスト、プルリクエストは大歓迎です。
この記事がMiscosoft VSTSへの関心を喚起することを本当に望んでいます。MiscosoftVSTSは、私の意見では、大企業だけでなく小規模の柔軟なチームにとっても優れたグループワークツールです。
コンスタンチン・ネラドフスキー、
テスト自動化責任者、
Otkritie Bank