LoginSignup
6
8

More than 1 year has passed since last update.

【ABAP】ABAP Unitを使ってみよう(1) ~簡単なところから

Last updated at Posted at 2019-12-06

ABAPのテスト自動化

ABAPにもテスト自動化の仕組みが用意されていることをご存じでしょうか。私はABAP to the Futureという本で初めて知りました。この本の5章にテスト自動化の仕組み(ABAP Unit)について紹介されています。ただ、テストクラス全体がどういう構成になっているかよくわからなかったので、実際に手を動かしてみることにしました。初めてなので、まずは簡単なところから。徐々に複雑なシナリオにも挑戦していきたいと思います。

目次
【ABAP】ABAP Unitを使ってみよう(1) ~簡単なところから(今回)
【ABAP】ABAP Unitを使ってみよう(2) ~Test Doubleで依存性を解決する
【ABAP】ABAP Unitを使ってみよう(3) ~CDSビューのテスト
【ABAP】ABAP Unitを使ってみよう(4) ~CDS:セッション変数をTest Doubleにしようとして失敗した話

ABAP Unitの構成

テストはローカルクラスの中に書きます。テストクラスからは、外部のクラスのメソッドをテストすることができます。
image.png
【疑問】テスト用クラスのグローバルの部分は使わないのか?
本番用のコードをここに書くこともできます。その場合、一つのクラスに本番用のコードと、(ローカルクラスとして)テスト用のコードが同居することになります。テストクラスの構成をどうしたらよいのかは、まだよくわかりません。複数のクラスを一か所でテストしたい場合は、テスト用のクラスを独立させたほうがよさそうです。

ABAP Unitを使ったTest-Driven Develpmentの流れ

Test-Driven Development(TDD)とは、本番のコードより先にテストを書くという開発手法で、以下のサイクルで進めます。
1. テストコードを書く(テストは失敗)
2. 本番用のコードを実装してテストに通るようにする
3. テストコードと本番用コードをリファクタリング(改善)する
image.png
SAP - ABAP Development User Guideより引用

早速やってみる

手順

  1. 本番用のクラスを作る(ガラだけ)
  2. テスト用のクラスを作る
  3. テストを実行する
  4. 機能を実装して再テストする

1. 本番用のクラスを作る(ガラだけ)

以下のクラスをテスト対象とします。

CLASS zcl_mob49_class_under_test DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.



CLASS zcl_mob49_class_under_test IMPLEMENTATION.
ENDCLASS.

2. テスト用のクラスを作る

本番用のクラスとは別に、テスト用のクラスを作成します。テスト用のローカルクラスは"Test Classes"というタブの中に書きます。
image.png
"test"と打ってからCtrl+Spaceを押すと、テスト用のコードが提案されます。
image.png
以下が初期提案されたコードです。
image.png

テスト用のコード

*"* use this source file for your ABAP unit test classes
class ltcl_ definition final for testing
  duration short
  risk level harmless.

  private section.
    data:
      mo_class_under_test type ref to zcl_mob49_class_under_test.

    methods:
      setup,
      say_hello_world for testing.
endclass.


class ltcl_ implementation.
  METHOD setup.
    "テスト対象オブジェクトをインスタンス化する
    create OBJECT mo_class_under_test.

  ENDMETHOD.

  method say_hello_world .
    data: lv_message type string.

    mo_class_under_test->hello_world(
      EXPORTING
        i_name    = 'Unit Test'
      IMPORTING
        e_message = lv_message
    ).

    cl_abap_unit_assert=>assert_equals(
      EXPORTING
        act                  = lv_message             " 実際の結果
        exp                  = 'Hello, Unit Test !'   " 想定結果
        msg                  = 'hello world function not working' " エラーの場合のメッセージ
        quit                 = if_aunit_constants=>quit-test
    ).

  endmethod.

endclass.

ここでは2つのメソッドを実装しました。

  • setup: テスト用のメンバ変数の初期化などを行う。(最初に呼ばれるメソッド)
  • say_hello_world: これから実装するメソッドのテスト用。 メソッドからの返り値が想定した値と一致しているかチェックする。

有効化しようとすると、テスト対象のメソッドがまだ実装されていないためエラーになります。

Quick Fixでメソッドを実装

エラーになったメソッドの上で右クリックし、Quick Fixを選択します。
image.png
"Create method hello world"が提案されるので、それを選択します。
image.png
メソッド名やパラメータが提案されるので、必要に応じて調整し、Finishを押します。
image.png
テスト対象のクラスにメソッドのガラが実装されました。
image.png

3. テストを実行する

右クリック>Run As>ABAP Unit Testを選択します。
image.png
まだメソッドの中身を実装していないのでエラーになります。
image.png

4. 機能を実装して再テストする

hello_worldメソッドを実装します。

  METHOD hello_world.

    e_message = |Hello, { i_name } !|.

  ENDMETHOD.

再テストの結果はOKになりました。
image.png

テスト自動化、TDDについて思ったこと

以下、思ったことを箇条書きで。

  • どこまでテストするのか。すべてのメソッドをテストする必要がある?→汎用モジュールなどの場合、ルーチン単位でテストしているわけではなく、分岐網羅とかでやってる
  • 「テストコードの品質はどうやって担保するのか」と言われそう
  • 独立したテストができるように、依存関係を解決しなければならないのが厄介

参考

Unit Testing with ABAP Unit

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8