2016-07-14 10 views
1

私はこれらの線に沿って行くいくつかのプロトタイプのコードで始まっ:外部APIを呼び出すクラスを設計するとき、テストの実装が正しいですか?

// Omitted most definitions, return values checks, etc. 
// The real code is much bigger and uglier. 
serverId = socket(AD_INET, SOCK_STREAM, PROTO_ANY); 
setsockopt(serverId, SOL_SOCKET, SO_REUSEADDR, &reuseAddrOk, sizeof(int)); 
bind(serverId, &serverAddress, sizeof(serverAddress)); 
listen(serverId, waitQueueSize); 
clientId = accept(serverId, &clientAddress, sizeof(clientAddress)); 
read(clientId, clientBuffer, charsToRead); 

今私は(今のところ、物事は非常に汎用的にしようとしない非常に単純なクラスに機能を抽出し、このコードをリファクタリングしたいのですが... YAGNI)。このニーズを呼び出すためにあるため、その後

SocketServer server = SocketServer(parameters); 

:これは私が考えているインタフェースの一種である:例えば

SocketServer server = SocketServer(parameters); 
// SocketServer knows how to create a SocketClient...abstract factories, dependency injection, etc. etc. 
SocketClient client = server.accept(); 
string clientMessage = client.read(); 
client.write(serverMessage); 

SocketServerクラスは、新しいソケットサーバーを作成するためのすべての定型文をカプセル化システムAPI、私はそれを嘲笑する必要があります:

SocketServer server = SocketServer(systemAPI, parameters); 

ここで、このコードが正しいことをテストすることは何を意味していますか?それは私が確認できる出力を生成しません(あるいは、ファイルディスクリプタのように出力をカプセル化するためにこれを行うのがより良い)。私はモックAPIの正しい方法は、同様に、呼ばれていることを確認することができます:

testSocketCalledWithCorrectParameters() { 
    systemAPI = mock(SystemAPI).expect(once()).method("socket").with(
     SystemAPI.AF_INET, 
     SystemAPI.SOCK_STREAM, 
     SystemAPI.PROTO_AUTO 
    ); 
    ServerSocket(systemAPI, parameters); 
} 

これは私が代わりにインタフェースの実装をテストするに頼る必要があり、適切な状況ですか?悪いデザインのインターフェイスの臭いではなく、実装をテストすることを余儀なくされていますか?

私は実装のセットの期待を考えることができるすべての他のテスト:

testServerSocketIsCreatedWithCorrectDescriptor() { 
    dummyDescriptor = 10; 
    systemAPI = mock(SystemAPI).when("socket").return(dummyDescriptor); 
    server = SocketServer(systemAPI, parameters); 
    assertEquals(dummyDescriptor, server.descriptor); 
} 

/** 
* @expected SocketException 
*/ 
testThrowsExceptionIfErrorCreatingSocket() { 
    systemAPI = mock(SystemAPI).when("socket").return(SystemAPI.RETURN_ERROR); 
    SocketServer(systemAPI, parameters); 
} 

// etc. 

そして、私はsocketAPIのためにも、ユニットテストを書くべきか、私はちょうどそれは非常にになることを当然取るべきダンプラッパークラスで、外部APIへの呼び出しを委任するだけで何もしないので、テストする必要はありません。

+0

'X'が' Z'を提供するときに 'Y'を行うと仮定した場合、どうやってテストしますか? 'X'を呼び出して' Y'を与え、 'Z'の結果をテストします。できない場合は、基本的なインフラストラクチャを作成する必要があります。 –

+0

"*インターフェイスではなく実装をテストする*" - インターフェイスをテストすることはどういう意味ですか? –

+0

@OliverCharlesworthもし 'add(a、b)'関数を持っていれば、この関数がどのように機能しているかにかかわらず、 'add(1,2)== 3'と' add(10,1)== 11'をテストできます。実装されました。 @EugeneSh。 – swahnee

答えて

0

1つ1つお答えします。

1.テストコールのプロパティ

この種の試験はdocumentational値(これはAPIを呼び出す方法です。)それはそれは本当に価値がある場合は、チェックを持っている - >多分文は十分に明確ですあなたのコードで。

2. testServerSocketIsCreatedWithCorrectDescriptor

私にとってはテストのこの種は、より多くの価値を持っています。ほとんどの場合、入力パラメータとアサートプロパティを示すtestCreationを書いています。車は建設のための車輪を必要とし、デフォルトでは4つの車輪、赤色と1つのステアリングホイールを持っています。

3. testThrowsExceptionIfErrorCreatingSocket

テストのこの種は、最も貴重なものです。彼らはさまざまな状況であなたのクラスの行動を定義し、保護します。私はここにアサーションがない。スローされる例外の種類。 この種のテストを考えてみてください。

4。テストシステムAPI

いいえ、ユニットテストではシステム動作をテストしないでください。特にモックではありません。 これはモジュールまたはエンドツーエンドのテストの一部です。

これが役に立ちます。

+0

お返事ありがとうございます。 「呼び出しプロパティをテストする」とはどういう意味ですか?モックの特定のメソッドは、特定の時間の量と呼ばれるテスト?ケース2では、テスト目的でのみ通常は(実装の一部として)隠されるプロパティを公開する価値があると思いますか?例外的な状況のテストにもっと重点を置くことで合意した。 – swahnee

+0

はい、私はモックの特定のメソッドが呼び出され、どの引数が渡されるかをテストすることを意味しました。ケース2の場合、テスト目的でのみserver.descriptorを公開することを意味しました。良い考えではありません。私のヒント:あなたのテストを聞いて、彼らはしばしば深刻な設計上の欠陥を明らかにする。テストが難しくて気味が悪ければ - テストの失敗ではなくデザインです – mrAtari

関連する問題