2011-01-20 4 views
1

단위 테스트가 처음입니다. 그리고 아래 코드를 단위 테스트 할 가치가 있는지 여부를 모르겠습니다. 델파이로 작성된 샘플 메소드는 다음과 같습니다.아래 코드는 단위 테스트의 가치가 있습니까?

function TCoreAudio.CreateAudioClient: IAudioClient; 
var 
    MMDeviceEnumerator: IMMDeviceEnumerator; 
    MMDevice: IMMDevice; 
    MixFormat: PWaveFormatEx; 
    AudioClient: IAudioClient; 
    HR: HResult; 
begin 
    Result := nil; 

    if CheckWin32Version(6, 0) then // The Core Audio APIs were introduced in Windows Vista. 
    begin 
    HR := GetInstance().CoCreateInstance(CLSID_MMDeviceEnumerator, nil, CLSCTX_ALL, 
     IMMDeviceEnumerator, MMDeviceEnumerator); 
    if Failed(HR) then 
     Exit; 
    HR := MMDeviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, MMDevice); 
    if Failed(HR) then 
     Exit; 
    HR := MMDevice.Activate(IAudioClient, CLSCTX_ALL, nil, AudioClient); 
    if Failed(HR) then 
     Exit; 
    HR := AudioClient.GetMixFormat(MixFormat); 
    if Failed(HR) then 
     Exit; 
    HR := AudioClient.Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 0, 0, MixFormat, nil); 
    CoTaskMemFree(MixFormat); 
    if Failed(HR) then 
     Exit; 

    Result := AudioClient; 
    end; 
end; 

단위 테스트 가치가있는 메소드입니까? 그렇다면 테스트를 위해 필요한 부분은 무엇입니까?

감사합니다.

답변

3

단위 테스트는 일반적으로 상향식 접근 방식입니다. 그래서 당신은 당신의 함수에서 사용되는 클래스들을 단위 테스트하기 시작할 것입니다. 이 모든 클래스가 단위 테스트로 덮여 있는지 확인한 후에는 함수 CreateAudioClient에 대한 단위 테스트를 만들 수 있습니다. 당신은 일반적으로 유닛이 클래스의 인터페이스가 아닌 함수 또는 프로 시저의 몸을 테스트

AudioClient := CreateAudioClient; 
CheckNotNil (AudioClient); 

참고 :이 기능에 대한 단위 테스트는 다음과 같이, 아마 매우 간단합니다.

희망이 있습니다.

가 IT에 대한 단위 테스트를 작성하는 방법을 쉽게
  • :

    그것이 가치가 있는지 질문은, 요소의 수에 따라 달라집니다? 얼마나 노력해야할까요?

  • 이 부분은 얼마나 중요합니까? 이 부분이 얼마나 중요한지에 따라 대답은 항상 "예, 단위 테스트의 가치가 있습니다"라고 대답 할 수도 있습니다.
  • 얼마나 바뀔까요? 이 방법이 미래에 어딘가에서 바뀔 수도 있다고 생각하면 단위 테스트를 추가하면 나중에 오류가 발생하지 않습니다.
+0

그러나 Windows XP 컴퓨터에서 실행하면 제안 된 샘플 단원 테스트 (AudioClient : = CreateAudioClient; CheckNotNil (AudioClient);)는 실패하고 Windows Vista 이상에서 실행하면 통과합니다. – CodeSnake

+0

@ CodeSnake 테스트에 쓸 필요가있는 내용입니다. –

0

이 방법에 대한 변경 사항이 실제로 얼마나 자주 발생할지에 따라 달라집니다 ... 이미 단위 테스트가 있다면, 그렇습니다. 그렇지 않으면 실제로 당신에게 달렸습니다.하지만 저는 다른 유닛의 다른 메소드를 호출하기 때문에 전체 유닛에서이 메소드 만 테스트하는 것이 좋습니다.

결론은 전체 프로젝트에 테스트를 추가하는 것이 가장 좋은 방법입니다. 그렇지 않으면 "부분 테스트"에서 어떤 가치도 볼 수 없습니다.

6

당신이 직면 한 문제는 테스트해야하는지 여부가 아닌 테스트 방법입니다.

이것은 여러 가지 이유로 실패 할 수있는 여러 가지 COM 호출에 대한 래퍼입니다. 이러한 가능한 COM 실패 조건은이 루틴을 테스트하는 가장 중요한 요소입니다. 하지만 쉽게 COM 루틴을 실패하게 만들 수는 없습니다. 이러한 COM 장애 모드를 테스트하려면 모의 (mock)를 사용해야하며 이는 사용자가있는 곳으로부터 도약입니다.

+1

그 방법 내에서 사용되는 모든 인터페이스를 조롱하고 Failed (HR), Exit (끝내기)를 수행 할 때마다 독립적으로 실패 여부를 테스트해야합니다. 성명서? – CodeSnake

+0

@ CodeSnake 글쎄요, 모든 실패 경로를 테스트하고 미래의 변경으로 인해 그 경로가 깨지지 않았 으면하고 싶은 것입니다. 특히 매력적인 일은 아닙니다! –

+2

나는이 경우 (a) 조롱 노력이 크고 (b) 기능의 복잡성이 낮기 때문에 동의 할 가치가 없다. – jpfollenius

3

응용 프로그램과 타사 API (시스템 API 포함) 간의 인터페이스 역할을하는 클래스를 단위 테스트 할 때 클래스가 호출하고 API에 올바르게 응답하는지 테스트하려고 할 때. API로 전달되는 내용을 감지하고 적절한 응답을 반환하는 방법이 없으면이를 수행 할 수 없습니다.

귀하의 경우에는 IAudioClient를 얻기 위해 일련의 호출을하고 있습니다. 네가 너무 많이하고 있다고 말하고 싶다. 함수에서 하나 이상의 조건문이 하나의 조건문이 너무 많습니다 (나는 그 개념과 혼동을 일으킨 것 같습니다). 개별적으로 테스트 할 수있는 몇 가지 기능을 제공합니다.

function TCoreAudio.CreateAudioClient: IAudioClient; 
var 
    MMDeviceEnumerator: IMMDeviceEnumerator; 
    MMDevice: IMMDevice; 
    MixFormat: PWaveFormatEx; 
    AudioClient: IAudioClient; 
begin 
    Result := nil; 
    if IsVista then 
    try 
     MMDeviceEnumerator := GetMMDeviceEumerator; 
     MMDevice := GetMMDevice(MMDeviceEnumerator); 
     AudioClient := GetAudioClient(MMDevice); 
     MixFormat := GetMixFormat(AudioClient); 
     InitializeAudioClient(AudioClient, MixFormat); 
     Result := AudioClient; 
    except 
     //Handle exception 
    end; 
end; 

function TCoreAudio.IsVista: boolean; 
begin 
    Result := CheckWin32Version(6, 0); 
end; 

function TCoreAudio.GetMMDeviceEnumerator: IMMDeviceEnumerator; 
begin 
    HR := GetInstance().CoCreateInstance(CLSID_MMDeviceEnumerator, nil, CLSCTX_ALL, 
     IMMDeviceEnumerator, Result); 
    if Failed(HR) then 
     raise Exception.Create('Failed to create device enumerator'); 
end; 

function TCoreAudio.GetMMDevice(ADeviceEnumerator: IMMDeviceEnumerator): IMMDevice; 
begin 
    HR := MMDeviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, Result); 
    if Failed(HR) then 
     raise Exception.Create('Failed to retrieve device'); 
end; 

function TCoreAudio.GetAudioClient(ADevice: IMMDevice): IAudioClient; 
begin 
    HR := MMDevice.Activate(IAudioClient, CLSCTX_ALL, nil, Result); 
    if Failed(HR) then 
     raise Exception.Create('Failed to retrieve audio client'); 
end; 

function TCoreAudio.GetMixFormat(AAudioClient: IAudioClient): PWaveFormatEx 
begin 
    HR := AudioClient.GetMixFormat(Result); 
    if Failed(HR) then 
     raise Exception.Create('Failed to retrieve mix format'); 
end; 

procedure TCoreAudio.InitializeAudioClient(AAudioClient: IAudioClient, AMixFormat: PWaveFormatEx); 
begin 
    HR := AudioClient.Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 0, 0, AMixFormat, nil); 
    CoTaskMemFree(MixFormat); 
    if Failed(HR) then 
     raise Exception.Create('Audio client failed to initialize'); 
end; 

는 이제 API는 적절한 인수로 호출되고 보장하고 생산 코드를 제대로 처리되었는지 확인하는 오류 조건을 강요, 각 기능에 모의/가짜/스텁을 제공 할 수 있습니다.

생산 코드를 테스트해야하는지 묻지 않아도됩니다. 대답은 항상 예입니다. (경고 : 뻔뻔한 자기 승진) 나는 최근에 내 blog에 대해 썼다. 때때로 모든 문장 중 가장 무해한 것조차, 할당 문은 예상대로 작동하지 않습니다.

실제로 이제 깨진 것은 새로운 창조적 인 수업처럼 보이기 시작한 것입니다.

관련 문제