2009-12-15 3 views
5

내 사용자 정의 컨트롤에 대한 테스트 케이스를 작성합니다. MessageBox.Show를 사용하여 사용자 작업을 처리하거나 취소하라는 메시지가 나타납니다. 진행하려면 사용자 상호 작용을 모방하도록 단위 테스트를 어떻게 디자인합니까?단위 테스트 WinForms UI

논리를 중간 계층으로 이동시키기 위해 리팩터링하고 싶지 않습니다. 이것은 사용자 동의를 얻고 중간 계층 호출을 진행하는 간단한 경우입니다. 이 시나리오에 대한 UI를 재구성하는 모든 도움/아이디어도 도움이 될 것입니다.

+0

그렇다면이 컨트롤을 클릭 할 때 컨트롤이 수행하는 작업을 테스트하고 싶습니까? 또는 테스트 자체가 중간 계층의 테스트가 안전한지 확인하기위한 차단 메시지 상자 대화 상자가 있습니까? – Maslow

답변

6

버튼을 클릭하면 해당 click 이벤트를 호출하는 것 외에는 아무 것도 없습니다. 그래서 당신은 그 주위에서 당신의 테스트를 만들고 싶을 것입니다.

코드를 프론트 엔드에서 옮기고 비즈니스 조치를 중심으로 유닛 테스트를 작성하면 버튼을 클릭하여 호출 할 수 있습니다. 저자 편집 후

업데이트는
당신은 거기 클릭 '하면'여기를 클릭 '주위에 당신의 단위 테스트를 빌드 할 수 없습니다,이 같은 당신이 일을 분할 할 준비가 아니기 때문에 작동하도록하지 않을 수 있습니다 '. 다음 코드 상상 :

private int MyFunction() 
{ 
    bool insideVariable = false; 
    if(insideVariable) 
     return 1; 
    else 
     return 2; 
} 

당신은 단위 테스트 insideVariable가 true로 설정되어있는 경우에 할 수 없을것이다; 다음 중 하나를 수행 할 수 있습니다 다음 return 1 문이 GUI의 방법이되도록 return 1 문이

  • 리팩토링이 중간 계층 어딘가에 그래서

    1. 이 코드를 리팩토링. 그런 다음 해당 기능을 테스트 할 수 있습니다.

    애플리케이션 프론트 엔드는 대체하기가 쉽기 때문에 비즈니스 로직을 저장하지 않아야합니다. 유닛 테스트는 메인 GUI 옆에있는 또 다른 프런트 엔드입니다.

  • +0

    비슷한 물건을 SendKeys.SendWait 사용할 수 있지만 여기 ShowDialog는 블로킹 호출입니다. – SKG

    +0

    버튼을 실제로 클릭하지 말고 그냥 'new Form1(). Button1_Click (this, null)'과 같은 것입니다. . –

    +2

    +1 - UI에 실제로 UI 코드를 사용해야하는 충분한 논리가 UI에 포함되어 있으면 UI에 너무 많은 논리가 포함되어 있습니다. 예외에 주목할 가치가 있습니다. 프레젠테이션 로직은 항상 까다로울 뿐이지 만 일반적으로 테스트 가능한 코드는 UI에서 시작하지 않습니다. –

    3

    UI 방법이나 관련 방법을 게시하면 해결 방법을 훨씬 쉽게 제공 할 수 있습니다. 또한 TestMethod를 보면 불완전한 메소드까지도 도움이 될 수 있습니다.

    테스트 목적이 다른 클릭 가능성에서 어떤 결과가 발생하는지 판단하는 것이라면 어떻게해야합니까? 이렇게 될 것이다 (위쪽의 using Microsoft.VisualStudio.TestTools.UnitTesting;를 포함하는 기억)

    public class ClassUnderTest 
    { 
        private static Func<string, string, MessageBoxButtons, DialogResult> 
         _messageBoxLocator = MessageBox.Show; 
        public static Func<string, string, MessageBoxButtons, DialogResult> 
         MessageBoxDependency 
        { 
         get { return _messageBoxLocator; } 
         set { _messageBoxLocator = value; } 
        } 
    
        private void MyMethodOld(object sender, EventArgs e) 
        { 
         if (MessageBox.Show("test", "", MessageBoxButtons.YesNo) == 
          System.Windows.Forms.DialogResult.Yes) 
         { 
          //Yes code 
          AnsweredYes = true; 
         } 
         else 
         { 
          //No code 
    
         } 
        } 
    
        public bool AnsweredYes = false; 
    
        public void MyMethod(object sender, EventArgs e) 
        { 
         if (MessageBoxDependency(
            "testText", "testCaption", MessageBoxButtons.YesNo) 
          == 
          System.Windows.Forms.DialogResult.Yes) 
         { 
          //proceed code 
          AnsweredYes = true; 
         } 
         else 
         { 
          //abort code 
         } 
    
    
        } 
    } 
    

    다음 시험 방법을 :

    이 같은 Inversion of ControlDependency Injection를 사용하여 MessageBox을 트리거 실제 방법을 설정할 수 있습니다

    [TestMethod] 
        public void ClassUnderTest_DefaultAnsweredYes_IsFalse() 
        { 
         var classUnderTest = new ClassUnderTest(); 
         Assert.AreEqual(false, classUnderTest.AnsweredYes); 
        } 
        [TestMethod] 
        public void MyMethod_UserAnswersYes_AnsweredYesIsTrue() 
        { 
         //Test Setup 
         Func<string, string, MessageBoxButtons, DialogResult> 
          fakeMessageBoxfunction = 
            (text, caption, buttons) => 
            DialogResult.Yes; 
    
         //Create an instance of the class you are testing 
         var classUnderTest = new Testing.ClassUnderTest(); 
         var oldDependency = Testing.ClassUnderTest.MessageBoxDependency; 
         Testing.ClassUnderTest.MessageBoxDependency = fakeMessageBoxfunction; 
         try 
         { 
          classUnderTest.MyMethod(null, null); 
          Assert.AreEqual(true, classUnderTest.AnsweredYes); 
          //Assert What are you trying to test? 
         } 
         finally 
         { //Ensure that future tests are in the default state 
          Testing.ClassUnderTest.MessageBoxDependency = oldDependency; 
         } 
        }