質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

90.51%

  • C++

    3451questions

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

  • テスト駆動開発

    64questions

    テスト駆動開発は、 プログラム開発手法の一種で、 プログラムに必要な各機能をテストとして書き、 そのテストが動作する必要最低限な実装を行い コードを洗練させる、といったサイクルを繰り返す手法の事です。

Visual StudioでGoogle Testが実行できない

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,044

AloneLeisure

score 7

前提・実現したいこと

テスト駆動開発を勉強しようと思い、Visual StudioでGoogle Testを使用しようとしましたが、実行できません。
インクルードディレクトリ、スタティックリンクライブラリの設定は行っており、コンパイルまでは通っています。
以下のリンクエラーが発生したまま、足踏みが続いている状況です。

発生している問題・エラーメッセージ

エラー    LNK2019    未解決の外部シンボル _main が関数 "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) で参照されました。    TestDrivenDevelopmentChapter1    c:\Users\***\documents\visual studio 2017\Projects\TestDrivenDevelopmentChapter1\TestDrivenDevelopmentChapter1\MSVCRTD.lib(exe_main.obj)    1    

該当のソースコード

「テスト駆動開発」の6ページまでのコードをC++に落とし込んだものになります。

MoneyTest.cpp(testTestDrivenDevelopmentChapter1プロジェクト内)

#include <gtest/gtest.h>

#include <Dollar.h>

TEST(MoneyTest, Multiplication) {
    Dollar five(5);
    five.times(2);
    EXPECT_EQ(10, five.amount);
}

Dollar.h(TestDrivenDevelopmentChapter1プロジェクト内)

#pragma once
class Dollar
{
public:
    Dollar(int amount);
    ~Dollar();

    void times(int multiplier);

    int amount;
};

Dollar.cpp(TestDrivenDevelopmentChapter1プロジェクト内)

#include "Dollar.h"

Dollar::Dollar(int amount)
{
}

Dollar::~Dollar()
{
}



void Dollar::times(int multiplier)
{
}

試したこと

エラーメッセージから推測するには、エントリポイントが見つからないのだと思います。
そこで、以下を試しました。

・MoneyTest.cppにInitGoogleTest()、RUN_ALL_TEST()を記述したmain関数を書く
→状況変わらず

・Dollar.cppに空のmain関数を書く
→当然ながら何もしないmain関数が実行されて終了する(テスト結果は表示されず)

・Dollar.cppにInitGoogleTest()、RUN_ALL_TEST()を記述したmain関数を書く
→InitGoogleTest()、RUN_ALL_TEST()の定義が見つからないコンパイルエラーが出る

補足情報(言語/FW/ツール等のバージョンなど)

言語:C++
開発環境:Visual Studio Community 2017
テストフレームワーク:Google Test 1.7.0

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

check解決した方法

+1

自己解決しました。
結論から言えば、プロジェクト本体とテストプロジェクトを分けず、同一のプロジェクトで扱う必要があったようです。
以下、TestDrivenDevelopmentChapter1(Dollar側)を「テストされる側のプロジェクト」、
testTestDrivenDevelopmentChapter1(MoneyTest側)を「テストする側のプロジェクト」と呼称し、
その後の経過を述べていこうと思います。

 件のリンクエラーについて

これについては、やはりmain関数が見つからないことが原因のようでした。
ただし、テストする側のプロジェクトではなく、テストされる側のmain関数だったようです。
そのためにDollar.cppにmain関数を書いた時にはリンクも通り実行できたのでしょう。

ただしGoogle Testの実行という目的は達せられないため、プロジェクトの実行順序を変更する必要がありました。
ソリューションのプロパティから[共通プロパティ]-[スタートアッププロジェクト]に移動し、
[シングルスタートアッププロジェクト]をテストする側のプロジェクトにする必要があったようです(ソリューション名と同一なため、デフォルトではテストされる側のプロジェクトになっていました)。
その後、今度は他のリンクエラーが出る形になりました。

スタートアッププロジェクト変更後の各種リンクエラー

まず、大量の(私の環境では508もの)LNK2005エラーが出力されました。
これについては検索すれば即座に解決しました。コード生成のランタイムライブラリをMTdにし、
リンクするスタティックリンクライブラリをDebugモードのものにして解決しました。

今度はDollarのコンストラクタ、デストラクタ、およびtimes関数について、LNK2019エラーが出力されました。
どうやらテストされる側のファイルとテストする側のファイルが同じプロジェクトに存在する必要があるようです。
ですので、epistemeさんのアドバイスに従い、テストする側のプロジェクトに
Dollar.hおよびDollar.cppを追加し、ようやくテストの結果が表示されました。

テストする側のプロジェクト削除

ただ、こうしなくてはいけないのではテストする側のプロジェクトが存在する意味がありません。
テストする側のプロジェクトを削除し、テストされる側のプロジェクトにMoneyTest.cppを追加、
そしてテストする側に行っていた各種インクルード・リンク設定をテストされる側のプロジェクトに行いました。
その際、epistemeさんのアドバイスのように . にインクルードパスを通す必要があるようです(MoneyTest.cppはテストする側のプロジェクトディレクトリ内にあるので)。
この構成にすれば、テストされる側のmain関数はそもそも問題にならなくなります(epistemeさんの構成はおそらくこの形なのだと思います)。

結局、冒頭にも述べたように、プロジェクト本体とテストプロジェクトを分けてはいけないというのが今回の問題の本質だったようです。
検索した限りでは両者を各個プロジェクトに分離している構成が多く見られるのですが、この点、腑に落ちないところです。

ともあれ、真摯に対応してくださったepistemeさん、hmmmさん、誠にありがとうございました。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/30 13:17

    私は例えば、最終製品のEXE(中身はほぼなしでLIBのコードを実行する),最終製品のEXEにリンクするLIB(ここに製品に必要な処理がはいる)、テスト用のEXEと3つのプロジェクトにしてます。テスト用のEXEのプロジェクトは製品用のLIBが使えるようにインクルードなども設定し、製品用のLIBをリンクさせて製品用の処理のテストを実行しています。

    キャンセル

  • 2017/12/30 15:36

    ご助言ありがとうございます。大変参考になります。

    現在の目的はGoogle Testを使ってC++でのテスト駆動開発を勉強することでしたので、当面は現在の1プロジェクト構成で進めてみようと思います。
    ただ、現在の構成ではソリューション・プロジェクトが大きくなった時に限界が来るだろうことも感じているので、
    その際にはhmmmさんのアドバイスが役に立ちそうです。

    キャンセル

+1

「テスト駆動開発」の6ページまでのコードをC++に落とし込んだものになります。

この本にはmain関数の記載はなかったんでしょうか?

・MoneyTest.cppにInitGoogleTest()、RUN_ALL_TEST()を記述したmain関数を書く
→状況変わらず

これでできるような気がしますが、Main.cppと別ファイルに分けてみてはどうですか?

Main.cpp

#include <gtest/gtest.h>

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/29 22:37 編集

    ご回答ありがとうございます。

    当該書籍ではJava、JUnit、Eclipse環境での解説となっています。
    それをC++、Google Test、Visual Studio環境でやりたいというのは完全に私のわがままになります。
    ともかくこうした背景事情にあるので書籍に環境構築面を期待することはできません。

    頂いたアドバイス通り、テスト側のプロジェクトでMain.cppを作成しましたが、状況は変わりませんでした。

    キャンセル

  • 2017/12/30 01:02 編集

    エラー内容のexe_main.objというのはVCランタイム内のコードで、この中でmainを実行しています。AloneLeisureさんが推測している通りmainを含んだobjが足りずリンクできないだけのはずです。回答に記載の内容でリンクできないのであれば、ソースコードの問題ではなくプロジェクトファイルなどに問題があるのでしょう。ソリューション内のファイルを一式githubなどにアップすることをお勧めします。

    キャンセル

  • 2017/12/30 09:48

    度々ありがとうございます。

    自己解決にも記述しましたが、おっしゃる通り、プロジェクトやソリューションの構成の問題が大きかったようです。

    キャンセル

+1

gtest-packageのgoogletest/src にある gtest-all.cc と gtest_main.cc をプロジェクトに追加して一緒にコンパイル/リンクするだけなんぢゃがの。

  • console-application でプロジェクト作成
  • googletest-release-1.7.0/include と googletest-release-1.7.0/src そして . にinclude-pathを通す
  • プロジェクトに googletest-release-1.7.0/src/gtest_main.cc および gtest-all.cc を追加する
  • テストおよびテスト対象(~.h,~.cpp)を追加

これだけでできたです。  

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/29 22:43

    ご回答ありがとうございます。

    折角頂いた回答に更に質問するのは恐縮なのですが、その2ファイルをどう追加するのでしょうか。

    テスト側のプロジェクトに当該2ファイルを追加しましたが、やはり同様のエラーが出ます。
    当該2ファイルを含んでいるgtest.vcxprojおよびgtest_main.vcxprojをソリューションに追加し、テスト側のプロジェクトが2プロジェクトを参照するようにして実行しても、結果は同様。
    さらに、上記2つを組み合わせても同じ結果でした。

    私が未熟なのは重々承知していますが、gtest-all.ccおよびgtest-main.ccの追加方法をご教授くださると助かります。

    キャンセル

  • 2017/12/29 23:02

    プロジェクトまるごと差し上げます。twitter:@epitwit にメッセージください。

    キャンセル

  • 2017/12/29 23:15

    失礼を承知で申し上げます。
    このサイトは私だけでなく、後に他の初心者の方も解決方法を求めて来訪する場所です。
    裏口でファイルのやり取りをして「解決しました」ではその用をなしません。
    言葉での回答をお願いします。

    キャンセル

  • 2017/12/29 23:23

    加筆しといた。

    キャンセル

  • 2017/12/29 23:51

    度々ありがとうございます。

    ただ、残念ながら未だ成功していません。
    srcへのインクルードパスが通っていなかったのはご指摘により修正しましたが、結果は質問時と変わりません。

    キャンセル

  • 2017/12/29 23:55 編集

    僕とこでは一発OKでした。
    main()はgtest_main.ccで実装されているので"mainが見つからん"はずがないのです。
    お役に立てず申し訳ない。

    キャンセル

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

  • ただいまの回答率 90.51%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C++

    3451questions

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

  • テスト駆動開発

    64questions

    テスト駆動開発は、 プログラム開発手法の一種で、 プログラムに必要な各機能をテストとして書き、 そのテストが動作する必要最低限な実装を行い コードを洗練させる、といったサイクルを繰り返す手法の事です。