🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

3608閲覧

Assert::AreEqual<int>(~~)の<int>は何?

J-GUN

総合スコア24

ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/12/23 11:15

編集2019/12/25 12:13

現在、ユニットテストの自動化をしようと思いコードを書いているところです。
あるコードを書いたところで
エラー C3690 文字列リテラルが予期されるところで~~
エラー C2338 Test writer must define specialization of ToString~~
といったエラーが発生しました。

解決策を調べたところこちら
Assert::AreEqual(~~)を
Assert::AreEqual<int>(~~)
のように書くと直る、と書いてあり試してみたところ確かにエラーが消えました。
(Assert::AreEqualを他に使っている箇所で出なかったあたり複合的な要素が絡んだエラーなのでしょうが)

ここで疑問なのがこの<int>にはどういう役割や効果があるのか、という点です。
キャストでもなさそうですし・・・今まで関数名の後ろにつけるといった書き方をしたことがありません。

お分かりになる方がいらっしゃいましたら教えていただけると助かります。

追記
本題とは直接関係ないかと思いソースを省略しましたが記載しました。
環境はSaito Atsushiさんがおっしゃる通りVisual Studio 2015 for Windows DesktopでMicrosoft::VisualStudio::CppUnitTestFrameworkを使用しています。

C++

1class ClassA{ 2 public: 3 double dArray[RAW][COL]; 4 unsigned short usArray[RAW][COL]; 5 double dVal; 6 unsigned short usVal; 7 8 public: 9 Reset(); 10}; 11

C++

1namespace TestClassA{ 2 TEST_CLASS(TestClassAReset){ 3 public: 4 TEST_METHOD(Reset_dArray) 5 TEST_METHOD(Reset_usArray) 6 TEST_METHOD(Reset_dVal) 7 TEST_METHOD(Reset_usVal) 8 9 private: 10 template <typename T> void TestArrayReset(T* arr, int raw, int col); 11 template <typename T> void TestArrayMatch(T* arr, int raw, int col, T compVal); 12 template <typename T> void TestValReset(T val); 13 template <typename T> void TestValMatch(T val, T comVal); 14 15 private: 16 ClassA* m_cl; 17 }; 18}

C++

1void TestClassAReset::Reset_dArray(){ 2 m_cl = new ClassA(); 3 TestArrayReset(&m_cl->dArray[0][0], RAW, COL); 4 delete m_cl; 5} 6 7void TestClassAReset::Reset_dVal(){ 8 // new, delete省略 9 TestArrayVal(&m_cl->dVal); 10} 11// Reset_usArray, Reset_usValは引数にusArray, usValを使用すること以外は同様のため省略 12 13template <typename T> void TestClassAReset::TestArrayReset(T* arr, int raw, int col){ 14 // m_clの値を0以外で初期化 15 m_cl->Reset(); 16 TestArrayMatch(arr, raw, col, (T)0); 17} 18 19template <typename T> void TestClassAReset::TestArrayReset(T* arr, int raw, int col, T compVal){ 20 for(int i = 0; i < RAW; i++){ 21 for(int j = 0; j < COL; j++){ 22 Assert::AreEqual(comVal, arr[i*COL + j]); // エラーになる 23 } 24 } 25} 26 27template <typename T> void TestClassAReset::TestValReset(T val){ 28 // m_clの値を0以外で初期化 29 m_cl->Reset(); 30 TestValMatch(val, (T)0); 31} 32 33template <typename T> void TestClassAReset::TestValMath(T val, T compVal){ 34 Assert::AreEqual(comVal, val); // エラーにならない 35}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2019/12/23 11:19

情報不足。コードと出典を示せ。
J-GUN

2019/12/25 12:14

本題とは直接関係ないかと思いソースを省略しましたが記載しました。
guest

回答1

0

ベストアンサー

環境が書かれていませんが、エラーの様子からすると Visual Studio で Microsoft::VisualStudio::CppUnitTestFramework を使った場合であると考えてよろしいですね? (標準ライブラリならともかく実行環境・ライブラリに固有の機能を使っていることが明らかな場合は明示するようにしてください。) 私自身は Visual Studio が動作する環境を用意していないので C++ 一般の知識とマイクロソフトのドキュメントソースコードを元に回答します。

<int> が何かという質問に対してはテンプレート引数ですというのが端的な回答です。 関数テンプレートは実際の引数から型を推論できる場合にはそれを使いますので陽にテンプレート引数を指定する必要はありませんが、推論できないとき、または通常の推論規則とは異なる解釈をして欲しいときには陽に指定する必要がある場合もあります。 実引数の型と指定した型が異なるときは暗黙の型変換が適用されます。 変換できないときはエラーです。

Assert::AreEqual の実際の定義の中では表示するメッセージを作成するために、与えられたオブジェクトを ToString 関数で文字列に変換するという処理が入っていて、 ToString が対応していない型だった場合にはエラーになるようです。

質問者が提示しているエラーの内容は、 Assert::AreEqual の実引数の型は ToString が対応していないという意味です。 しかし int に変換可能な型ではあるのでしょう。

ToString を特殊化するという方法でも対処できるそうです。 (たぶんオーバーロードでも良いと思います。)

投稿2019/12/23 14:22

SaitoAtsushi

総合スコア5684

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

J-GUN

2019/12/25 12:16

ご回答ありがとうございます。 ということはintに変換した上で比較している、ということになるのでしょうか。 ちなみにTestValResetでエラーとならずTestArrayResetでエラーとなる理由はお分かりになるでしょうか?
SaitoAtsushi

2019/12/26 10:46 編集

はい。 この場合はテンプレート引数として int を指定すれば int への変換となります。 エラーになっていたのは内部で文字列に変換する ToString 関数が unsigned short には対応していないからのようですね。 (double には対応しています。) TestValReset がエラーにならないのは使われていないからだと思います。 (省略している部分で使われているのでしょうか?) テンプレートは実際に使われるか明示的実体化を指示しなければ実体化 (インスタンス化) されません。 テンプレートは与えられる型によって振舞いが変わり、型次第で問題ないこともエラーになることもあります。 型が与えられるまではその判断が出来ないのでしないのです。 (判断できる部分は判断しますけど。) ちなみに、 double や float のような型で単純に一致するかを比較するのは問題があるとされています。 たとえば 0.1 のようなキリのよい小数でも二進数として表現すると循環小数になりますので、これが誤差になるからです。 この誤差は計算機イプシロンと呼ばれています。 https://ja.wikipedia.org/wiki/%E8%A8%88%E7%AE%97%E6%A9%9F%E3%82%A4%E3%83%97%E3%82%B7%E3%83%AD%E3%83%B3 計算をしていくと誤差が蓄積されて理論上の値とはずれてしまいます。 誤差が大きくても小さくてもキッカリ一致にはならないので「一致するか?」で判断するとだいたい一致しません。 Assert::AreEqual には許容誤差 (tolerance) を指定するオーバーロードがあるので、そちらを利用すべきです。 https://docs.microsoft.com/ja-jp/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference?view=vs-2019#general_are_equal
J-GUN

2019/12/26 12:14

TestValMathもReset_dVal→TestValReset→TestValMathで使ってるんですけど、エラーは出ないですね(上のやつだとReset_dVal→TestValResetを書き間違えてますね・・・) Assert::AreEqualの許容誤差は気づいてませんでした ありがとうございました
SaitoAtsushi

2019/12/26 12:51

TestClassAReset::Reset_dVal の定義の中の TestArrayVal は TestValReset の間違いだということですね? 渡している引数の &m_cl->dVal はポインタです。 0 はポインタに変換したときはヌルポインタになるのでポインタと比較出来てしまいます。 当然ながら、これはポインタを比較したい場面ではないと思うので単純なミスですね。 間違いによって通ってしまっているわけですね。
J-GUN

2019/12/28 14:49

間違い×エラーで一周してビルドが通ってしまった感じですね。 ご丁寧にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問