ServiceNowのScript IncludeでGlideRecordを使ってレコード一括更新を行う


概要

次のようなオブジェクトを引数にとって、Saleテーブルのproductが一致するレコードのunitpriceを一括更新するスクリプトをScript includeで作成し、その単体テストを実施する。

引数のデータ型
    var data = {
        unitprice: "500",
        product: "PPP"
    };

なお、Tableは下記で作成したSales Tableを使用する。
ServiceNowでTableを作成する

スクリプト作成手順

Script Includeを作成する。

Studioを使ってCreate Application FileでServer DevelopmentカテゴリーのScript Includeを選択してCreateをクリックする。
Nameに「updateProductPrice」を入力して「Submit」をクリックする。

スクリプトを入力する。

Scriptに下記の通り入力する。

var updateProductPrice = Class.create();
updateProductPrice.prototype = {
    initialize: function() {
    },
    update:function(data) {
        gs.info('update product price called!');
        gs.info('data = ' + data);
        var product = data.product;
        var unitprice = data.unitprice;

        gs.info('prodcut = ' + product);
        gs.info('price = ' + unitprice);

        var grSales = new GlideRecord('x_211750_angular_a_sales');

        grSales.addQuery('product',product);
        grSales.query();

        if(grSales.next()){
          grSales.unitprice = unitprice;
          grSales.update(); 
        }
    },

    type: 'updateProductPrice'
};

スクリプトの解説

        var product = data.product;
        var unitprice = data.unitprice;

引数のdataからキー名から値をそれぞれ取得する。

GlideRecord
        var grSales = new GlideRecord('x_211750_angular_a_sales');

GlideRecordを作成する。引数にはSales TableのNameを指定している。

検索条件を指定してレコードを取得する。

        grSales.addQuery('product',product);
        grSales.query();

ここでは、product項目 = 引数のproductを検索条件としてレコードを取得している。

        if(grSales.next()){
          grSales.unitprice = unitprice;
          grSales.update(); 
        }

next()で1件目のレコードが取得出来たら、レコードのunitpriceに引数のunitpriceを設定する。update()で、指定したproductのレコードのunitpriceが一括更新できる。

SQLにすると、
update sale set unitprice = unitprice where product = product;
の実行と同等の処理となる。

単体テストで動作を確認する

テスト作成

テストは、StudioではなくServiceNowのアプリケーションブラウザーのNavigatorのAutomated Test Framework -> Testsを選択して行う。

Testsのレコードリストの画面で「New」をクリックし新たにテストを作成する。
Nameに任意のテスト名を入力して一旦Submitをクリックして保存する。

保存すると、Test Stepのレコードリストが表示される。
「Add Test Step」でテストステップを追加していく。

テストレコードの追加するテストステップを追加

「Add Test Step」をクリックし、ServerカテゴリのRecord Insertを選択して「Next」をクリクする。

次のようにレコード追加の設定を行う。なお、Desciptionは設定内容から自動生成されるが、UnitPriceの金額がDescription内で誤差が発生している。

テスト対象のスクリプトを起動するテストステップを追加

「Add Test Step」をクリックし、ServerカテゴリのRun Server Side Scriptを選択して「Next」をクリックする。
Test Scriptに次の入力を行う。Test Scriptには使用例などのコメントが大量に記述されているが、一旦全て削除してから入力する。


(function(outputs, steps, stepResult, assertEqual) {
    // add test script here
    var requestData = {
        unitprice: "500",
        product: "PPP"
    };

    var updateProductPriceObj = new updateProductPrice();       
    updateProductPriceObj.update(requestData);

})(outputs, steps, stepResult, assertEqual);

requestDataオブジェクトにunitPriceとproductを設定しupdateProductPrice.updateの引数として渡してScript Includeのスクリプトを実行している。

テスト結果の確認のためテストステップを追加

「Add Test Step」をクリックし、ServerカテゴリのRun Server Side Scriptを選択して「Next」をクリックする。
Test Scriptに次の入力を行う。

(function(outputs, steps, stepResult, assertEqual) {
    // add test script here
    var grSales = new GlideRecord('x_211750_angular_a_sales');

    grSales.addQuery('product','PPP');
    grSales.query();

    if(grSales.next()){
        var unitPrice = grSales.getValue('unitprice');

        assertEqual({name: "unitPrice of Product PPP is updated!", shouldbe: 500, value: unitPrice});

        stepResult.setOutputMessage("レコードが正常の更新されていることを確認");
        return true;

    } else {

        stepResult.setOutputMessage("レコードが正常に更新されなかった");
        return false;
    }

})(outputs, steps, stepResult, assertEqual);

ここでは、GlideRecodeの説明は省略する。
テストで独自に使用するスクリプトについて解説する。
assertEqualは、name, shouldbe, valueを持つオブジェクトを引数にとり、テスト結果kの検証を行う。nameは検証内容を説明する文言、shouldbeは期待する値で、valueには実際の値を設定する。
shouldbeとvalueが一致しないとテスト失敗と判定される。

stepResult.setOutputMessageによってテスト結果をTest Result画面にログとして出力する。
テストが失敗の場合は、
return false;
を返すことでテスト失敗と判定される。
なおテスト成功の場合は、特にreturn true;を呼ばなくても成功と判定される。

最後に

実際の単体テストとしては、条件に不一致のレコードの更新されていないことの確認や、複数の対象レコードがあった場合の確認なども必要となるが、今回は手順の作成のみのため実施していない。