Nao000のぶろぐ

蝶を追っている少年になりたい

【現在時刻を含む処理のテスト】テスト容易な「午前1時59分59秒までは前日として扱う」コードとテストコード【PHP】

【ユニットテスト】テスト容易な「午前1時59分59秒までは前日として扱う」コードとテストコード【PHP】

時刻を含むテスト容易なコードってどんな感じなんでしょうね。自分なりのテスト容易なコードを書いてみました。

時刻を含むテスト容易なコードの書き方の定石ってあるのでしょうかね。

目次

  • 【ユニットテスト】テスト容易な「午前1時59分59秒までは前日として扱う」コードとテストコード【PHP】
    • 目次
    • 環境
    • composer.jsonの内容
    • ディレクトリ構成
    • 準備
    • 仕様
    • ユニットテスト容易なシステム上の日付を取得するコード
    • テストコード
    • PHPUnit実行
    • 終わり

環境

  • windows10 pro 64bit
  • PHP Version 7.4.9
  • Composer version 1.8.0
  • PHPUnit Version 9.4.2

composer.jsonの内容

    {
        "name": "nao000dotcom/testsdatetime",
        "require": {},
        "autoload": {
            "classmap": [
                "src/"
            ]
        },
        "require-dev": {
            "phpunit/phpunit": "^9"
        }
    }

ディレクトリ構成

    testsdatetime
    ├─src
    │  │─classes
    │  │   └─Sample.php # 時刻を扱うコード
    │  └─tests
    │      └─SampleTest.php # テストコード
    │─vendor
    │─composer.json
    └─composer.lock

準備

composer install して、composer dump-autoload します。今更ですが、autoload ってすごくないですか。

  1. composer install を実行します
  2. composer dump-autoload を実行します

仕様

  • 午前1時59分59秒までは前日として扱う
  • 午前2時00分00秒からはその日付として扱う
  • 例1: 2020年10月24日 01時59分59秒 は、システム上では前日の 2020年10月23日 として扱う
  • 例2: 2020年10月24日 02時00分00秒 は、システム上では前日の 2020年10月24日 として扱う
  • ミリ秒以下は考慮しません
  • 秒数までを考慮します

ユニットテスト容易なシステム上の日付を取得するコード

メソッドの引数に日付を文字列で形式 Y-m-d H:i:s で設定するメソッドを用意します。形式 Y-m-d H:i:s を保証する処理は用意しておりません。

    <?php

    class Sample
    {
        /**
         * 午前1時59分59秒までは前日として扱う
         * 午前2時00分00秒からはその日付として扱う
         */
        public function get_treat_as_execute_date($datetime_str = '') :string {

            $dt = new Datetime($datetime_str);

            $end_datetime_str = $dt->format('Y-m-d 01:59:59');

            $end_dt = new Datetime($end_datetime_str);

            if ($dt <= $end_dt) {

                return $dt->modify('-1 day')->format('Y-m-d');
            }

            return $dt->format('Y-m-d');
        }
    }

テストコード

月跨ぎ・年跨ぎ・うるう年・非うるう年、を考慮したテストコードを書いていますが、どのくらいテストするべきなのかよく分かっていません。

    <?php
    use PHPUnitFrameworkTestCase;

    final class SampleTest extends TestCase
    {
        public function test_2020年10月24日01時59分59秒は2020年10月23日として扱う()
        {
            $sample = new Sample();

            $actuall = $sample->get_treat_as_execute_date('2020-10-24 01:59:59');

            $expect = '2020-10-23';

            $this->assertEquals($expect, $actuall);
        }

        public function test_2020年10月24日02時00分00秒は2020年10月24日として扱う()
        {
            $sample = new Sample();

            $actuall = $sample->get_treat_as_execute_date('2020-10-24 02:00:00');

            $expect = '2020-10-24';

            $this->assertEquals($expect, $actuall);
        }

        public function test_月を跨ぐとき_2020年11月01日01時59分59秒は2020年10月31日として扱う()
        {
            $sample = new Sample();

            $actuall = $sample->get_treat_as_execute_date('2020-11-01 01:59:59');

            $expect = '2020-10-31';

            $this->assertEquals($expect, $actuall);
        }

        public function test_月を跨ぐとき_2020年11月01日02時00分00秒は2020年11月01日として扱う()
        {
            $sample = new Sample();

            $actuall = $sample->get_treat_as_execute_date('2020-11-01 02:00:00');

            $expect = '2020-11-01';

            $this->assertEquals($expect, $actuall);
        }

        public function test_年末年始_2021年01月01日01時59分59秒は2020年12月31日として扱う()
        {
            $sample = new Sample();

            $actuall = $sample->get_treat_as_execute_date('2021-01-01 01:59:59');

            $expect = '2020-12-31';

            $this->assertEquals($expect, $actuall);
        }

        public function test_年末年始_2020年01月01日02時00分00秒は2020年01月01日として扱う()
        {
            $sample = new Sample();

            $actuall = $sample->get_treat_as_execute_date('2021-01-01 02:00:00');

            $expect = '2021-01-01';

            $this->assertEquals($expect, $actuall);
        }

        public function test_うるう年の2月_2020年03月01日01時59分59秒は2020年02月29日として扱う()
        {
            $sample = new Sample();

            $actuall = $sample->get_treat_as_execute_date('2020-03-01 01:59:59');

            $expect = '2020-02-29';

            $this->assertEquals($expect, $actuall);
        }

        public function test_非うるう年の2月_2021年03月01日01時59分59秒は2021年02月28日として扱う()
        {
            $sample = new Sample();

            $actuall = $sample->get_treat_as_execute_date('2021-03-01 01:59:59');

            $expect = '2021-02-28';

            $this->assertEquals($expect, $actuall);
        }
    }

PHPUnit実行

失敗するコードを書いていないので成功しかしてないです。

    PS C:xampphtdocsstudy   estsdatetime> ./vendor/bin/phpunit tests
    PHPUnit 9.4.2 by Sebastian Bergmann and contributors.

    ........                                                            8 / 8 (100%)

    Time: 00:00.015, Memory: 4.00 MB

    OK (8 tests, 8 assertions)
    PS C:xampphtdocsstudy   estsdatetime>

終わり

以上です。