Pleasanter で遊ぼう! ということで Pleasanter にテストを書いていきたいと思います。
■ なぜテストを書くのか?
プログラムでテストを書くのはなぜでしょう? そう、変更をするためです。テストがあることでコードの変更が可能になります。
つまりテストのプルグラムの改修、機能追加、修正、その他、地獄です。コードが意図せぬ場所に意図せぬ影響を与えてしまいバグが頻発し苦しむことになります。
■ テストだけでよいのか
ここで問題です。テストさえあればコードの変更は可能なのでしょうか? いいえ、パフォーマンスも必要です。
プログラムへのインプットとアウトプットが正しくても劇的に遅くなるようでは、無事変更できたとは言えません。
■ 測定方法
BenchmarkDotNet を使うのが第一の選択肢でしょう。
ただしやってみたけれど、ユニット テストと併用するには厳しいですね。これはある程度以上固まった単位での計測が使いどころです。ユニット テストの単位では測定に時間がかかりすぎてしまいます。
■ 結果
とはいえせっかく測定したので、手順と結果を。
測定対象は、ここでテストを書いた Decimals クラスです。
| Method | Mean | Error | StdDev | Median | |------------------------------------------------------------------------- |------------:|----------:|----------:|------------:| | TrimEndZero_ShouldReturnZero_WhenInputIsZero | 32.89 ns | 0.666 ns | 1.435 ns | 32.25 ns | | TrimEndZero_ShouldReturnSameNumber_WhenInputHasNoTrailingZeros | 715.18 ns | 8.292 ns | 7.351 ns | 716.01 ns | | TrimEndZero_ShouldReturnTrimmedNumber_WhenInputHasTrailingZeros | 750.37 ns | 14.535 ns | 20.376 ns | 743.69 ns | | TrimEndZero_ShouldReturnTrimmedNumber_WhenInputHasTrailingZeros29 | 846.95 ns | 7.769 ns | 6.488 ns | 845.38 ns | | TrimEndZero_ShouldReturnTrimmedNumber_WhenInputIsNull | 50.96 ns | 1.010 ns | 1.898 ns | 50.26 ns | | TrimEndZero_ShouldReturnTrimmedNumber_WhenInputAllowNullIsZero | 156.50 ns | 2.939 ns | 2.749 ns | 156.36 ns | | TrimEndZero_ShouldReturnTrimmedNumber_WhenInputAllowNullHasTrailingZeros | 1,017.94 ns | 20.169 ns | 42.101 ns | 1,001.96 ns |
■ 手順
learn.microsoft.com NuGet でパッケージ BenchmarkDotNet をインストール。
<Project Sdk="Microsoft.NET.Sdk"> <ItemGroup> <PackageReference Include="BenchmarkDotNet" Version="0.14.0" /> </ItemGroup>
測定したいロジックをメソッドにして BenchmarkDotNet.Attributes.Benchmark 属性を付ける。
using BenchmarkDotNet.Attributes; namespace PleasanterBenchmark.Libraries.Utilities { public class BenchmarkDecimals { [Benchmark] public void TrimEndZero_ShouldReturnZero_WhenInputIsZero() => Implem.Libraries.Utilities.Decimals.TrimEndZero(0m); [Benchmark] public void TrimEndZero_ShouldReturnSameNumber_WhenInputHasNoTrailingZeros() => Implem.Libraries.Utilities.Decimals.TrimEndZero(123.45m); [Benchmark] public void TrimEndZero_ShouldReturnTrimmedNumber_WhenInputHasTrailingZeros() => Implem.Libraries.Utilities.Decimals.TrimEndZero(123.4500m); [Benchmark] public void TrimEndZero_ShouldReturnTrimmedNumber_WhenInputHasTrailingZeros29() => Implem.Libraries.Utilities.Decimals.TrimEndZero(9.999_000_000_000_000_000_000_000_000m); [Benchmark] public void TrimEndZero_ShouldReturnTrimmedNumber_WhenInputIsNull() => Implem.Libraries.Utilities.Decimals.TrimEndZero(null); [Benchmark] public void TrimEndZero_ShouldReturnTrimmedNumber_WhenInputAllowNullIsZero() => Implem.Libraries.Utilities.Decimals.TrimEndZero((decimal?)0m); [Benchmark] public void TrimEndZero_ShouldReturnTrimmedNumber_WhenInputAllowNullHasTrailingZeros() => Implem.Libraries.Utilities.Decimals.TrimEndZero((decimal?)123.4500m); }
BenchmarkDotNet.Running.BenchmarkRunner.Run で測定されるメソッドを書いたクラスを指定して実行。
using BenchmarkDotNet.Running; var _ = BenchmarkRunner.Run<PleasanterBenchmark.Libraries.Utilities.BenchmarkDecimals>();
■ 時間
235.5812798 秒かかりました。