java 프로그래머가 더 좋은 단원 테스트를 작성하는 7가지 기교

9300 단어 java단원 테스트
테스트는 개발의 매우 중요한 부분으로 어느 정도에 응용 프로그램의 운명을 결정할 수 있다.좋은 테스트는 초기에 응용 프로그램의 붕괴를 초래하는 문제를 포착할 수 있지만, 비교적 나쁜 테스트는 종종 고장과 정지를 초래한다.
세 가지 주요 유형의 소프트웨어 테스트가 있는데 그것이 바로 단원 테스트, 기능 테스트와 통합 테스트이다. 그러나 이 논문에서 우리는 개발자급 단원 테스트를 토론할 것이다.내가 구체적인 세부 사항을 깊이 있게 이야기하기 전에, 우리 먼저 이 세 가지 테스트의 상세한 내용을 되돌아봅시다.
하나.소프트웨어 개발 테스트의 유형
단원 테스트는 각 코드 구성 요소를 테스트하고 코드가 예상한 방식에 따라 작동하는지 확인하는 데 사용된다.단원 테스트는 개발자가 작성하고 집행한다.대부분의 경우 JUnit이나 TestNG 같은 테스트 프레임워크를 사용합니다.테스트 용례는 일반적으로 방법 단계에서 쓰고 자동화를 통해 실행된다.
통합 테스트 검사 시스템이 하나의 전체로 작동하는지 여부.통합 테스트도 개발자가 완성하지만 단일 구성 요소를 테스트하는 것이 아니라 크로스 구성 요소를 테스트하는 데 목적을 둔다.시스템은 코드, 데이터베이스, 웹 서버 등 많은 단독 구성 요소로 구성되어 있다.통합 테스트는 구성 요소 배선, 네트워크 접근, 데이터베이스 문제 등 문제를 발견할 수 있다.
기능 테스트는 주어진 입력 결과와 규범을 비교함으로써 모든 기능이 정확하게 실현되었는지 검사한다.통상적으로 이것은 개발자 등급이 아니다.기능 테스트는 단독 테스트 팀에서 실행한다.테스트 용례는 규범에 근거하여 작성하고 실제 결과와 예상 결과를 비교한다.Selenium 및 QTP와 같은 자동화된 기능 테스트에 사용할 수 있는 몇 가지 도구가 있습니다.
앞에서 말한 바와 같이 단원 테스트는 개발자가 코드가 정상적으로 작동하는지 확인하는 데 도움을 줄 수 있다.이 블로그에서 나는 자바에서 단원 테스트에 유용한 힌트를 제공할 것이다.
2.프레임워크를 사용하여 단원 테스트에 사용
Java는 셀 테스트에 사용할 프레임워크를 제공합니다.TestNG와 JUnit은 가장 유행하는 테스트 프레임워크입니다.JUnit 및 TestNG의 주요 기능:
  1. 쉽게 설정하고 실행할 수 있습니다.
  2. 주석을 지원합니다.
  3. 일부 테스트를 무시하거나 그룹화할 수 있습니다.
  4. 매개 변수화 테스트를 지원합니다. 즉, 실행할 때 서로 다른 값을 지정하여 단원 테스트를 실행합니다.
  5. Ant, Maven, Gradle 등의 구축 도구와 통합하여 자동화된 테스트 실행을 지원합니다.
EasyMock은 아날로그 프레임워크로 JUnit과 TestNG 같은 단원 테스트 프레임워크입니다.EasyMock 자체는 완전한 프레임워크가 아닙니다.그것은 테스트에 편리하도록 시뮬레이션 대상을 만드는 능력을 추가했을 뿐이다.예를 들어 우리가 테스트하고자 하는 방법은 데이터베이스에서 데이터를 얻는 DAO 클래스를 호출할 수 있다.이 경우 EasyMock은 하드 인코딩 데이터를 반환하는 MockDAO를 만드는 데 사용됩니다.이것은 우리로 하여금 데이터베이스 접근을 걱정할 필요가 없이 우리의 의향을 쉽게 테스트할 수 있게 한다.
셋.테스트 구동 개발을 신중하게 사용하다
테스트 드라이브 개발(TDD)은 소프트웨어 개발 과정으로 이 과정에서 어떤 인코딩을 시작하기 전에 우리는 수요를 바탕으로 테스트를 작성한다.아직 인코딩이 되지 않았기 때문에, 테스트는 처음에는 실패할 것이다.테스트를 통과하기 위해 최소한의 코드를 쓰십시오.그리고 최적화될 때까지 코드를 재구성합니다.
목표는 모든 수요를 덮어쓰는 테스트를 작성하는 것이지, 처음부터 코드를 쓰는 것이 아니라, 심지어는 수요를 만족시키지 못할 수도 있다.TDD는 단순한 모듈화 코드를 초래하고 유지보수가 쉽기 때문에 위대하다.전체적인 개발 속도가 빨라져 결함을 발견하기 쉽다.이 밖에 단원 테스트는 TDD 방법의 부산물로 만들어졌다.
그러나 TDD는 모든 상황에 적합하지 않을 수도 있다.디자인이 복잡한 프로젝트에서 테스트 용례를 통과하기 위해 가장 간단한 디자인에 전념하고 미리 생각하지 않으면 커다란 코드 변경을 초래할 수 있다.그 밖에 TDD 방법은 유류 시스템, GUI 응용 프로그램이나 데이터베이스와 함께 작업하는 응용 프로그램과 상호작용하는 시스템에 사용하기 어렵다.또한 테스트는 코드의 변화에 따라 업데이트되어야 한다.
따라서 TDD 방법을 결정하기 전에 상술한 요소를 고려하고 프로젝트의 성격에 따라 조치를 취해야 한다.
사.코드 덮어쓰기 측정
코드 덮어쓰기는 단위 테스트를 실행할 때 실행되는 코드 양을 백분율로 측정합니다.일반적으로 높은 커버율의 코드는 검출되지 않은 오류를 포함할 확률이 낮다. 왜냐하면 더 많은 원본 코드가 테스트 과정에서 실행되기 때문이다.코드 오버레이를 측정하는 몇 가지 Best Practice는 다음과 같습니다.
  1. Clover, Corbetura, JacoCo 또는 Sonar와 같은 코드 덮어쓰기 도구를 사용합니다.도구를 사용하면 테스트의 질을 향상시킬 수 있다. 왜냐하면 이 도구들은 테스트를 거치지 않은 코드 구역을 가리키고, 이 분야를 커버하기 위해 추가 테스트를 개발할 수 있기 때문이다.
  2. 새 기능을 쓸 때마다 새 테스트 덮어쓰기를 쓰십시오.
  3. 테스트 용례가 코드를 덮어쓰는 모든 지점, 즉if/else 문장을 확보해야 합니다.
높은 코드 덮어쓰기는 테스트가 완벽하다는 것을 보장할 수 없기 때문에 조심해야 합니다!
다음 concat 방법은 부울 값을 입력으로 받아들이고 부울 값이true일 때만 두 개의 문자열을 추가합니다.

public String concat(boolean append, String a,String b) {
  String result = null;
  If (append) {
   result = a + b;
       }
  return result.toLowerCase();
}
 :
@Test
public void testStringUtil() {
  String result = stringUtil.concat(true, "Hello ", "World");
  System.out.println("Result is "+result);
}
이 경우 테스트를 실행하는 값은true입니다.테스트가 실행될 때, 그것은 통과될 것이다.코드 덮어쓰기 도구가 실행될 때, 코드 덮어쓰기 100%를 표시합니다. 왜냐하면 concat 방법의 모든 코드가 실행되기 때문입니다.단, 테스트가 false로 실행되면 NullPointerException이 던져집니다.그래서 100%의 코드 커버율은 테스트가 모든 장면을 커버했다는 것을 진정으로 나타내지 않고 테스트가 양호하다는 것을 설명할 수 없다.
5.가능한 한 테스트 데이터를 외부화하다
JUnit4에 앞서 테스트 용례가 실행될 데이터는 테스트 용례에 하드코딩되어야 합니다.이로 인해 제한이 생겼다. 서로 다른 데이터를 사용하여 테스트를 실행하기 위해서는 테스트 용례 코드가 수정되어야 한다.단, JUnit4와 TestNG는 원본 코드를 변경하지 않고 서로 다른 데이터 집합에 대한 테스트 용례를 실행할 수 있도록 외부화된 테스트 데이터를 지원합니다.
다음 MathChecker 클래스에서는 숫자가 홀수인지 확인하는 방법이 있습니다.

public class MathChecker {
  public Boolean isOdd(int n) {
   if (n%2 != 0) {
    return true;
   } else {
    return false;
   }
  }
 }
다음은 MathChecker 클래스의 TestNG 테스트 용례입니다.

public class MathCheckerTest {
  private MathChecker checker;
  @BeforeMethod
  public void beforeMethod() {
   checker = new MathChecker();
  }
  @Test
  @Parameters("num")
  public void isOdd(int num) {
   System.out.println("Running test for "+num);
   Boolean result = checker.isOdd(num);
   Assert.assertEquals(result, new Boolean(true));
  }
 }
TestNG
다음은 테스트ng입니다.테스트를 수행할 데이터가 있는 xml(TestNG용 구성 파일):

<?xml version="1.0" encoding="UTF-8"?>
 <suite name="ParameterExampleSuite" parallel="false">
 <test name="MathCheckerTest">
 <classes>
  <parameter name="num" value="3"></parameter>
  <class name="com.stormpath.demo.MathCheckerTest"/>
 </classes>
  </test>
  <test name="MathCheckerTest1">
 <classes>
  <parameter name="num" value="7"></parameter>
  <class name="com.stormpath.demo.MathCheckerTest"/>
 </classes>
  </test>
 </suite>
이런 상황에서 테스트는 두 번, 값 3과 7을 각각 한 번씩 실행된다는 것을 알 수 있다.XML 프로필을 통해 테스트 데이터를 지정하는 것 외에 DataProvider 주석을 통해 클래스에서 테스트 데이터를 제공할 수 있습니다.
여섯.JUnit
TestNG와 유사하게 테스트 데이터도 JUnit에 외부화할 수 있다.다음은 위의 MathChecker 클래스와 같은 JUnit 테스트 용례입니다.

@RunWith(Parameterized.class)
 public class MathCheckerTest {
  private int inputNumber;
  private Boolean expected;
  private MathChecker mathChecker;
  @Before
  public void setup(){
   mathChecker = new MathChecker();
  }
  // Inject via constructor
  public MathCheckerTest(int inputNumber, Boolean expected) {
   this.inputNumber = inputNumber;
   this.expected = expected;
  }
  @Parameterized.Parameters
  public static Collection<Object[]> getTestData() {
   return Arrays.asList(new Object[][]{
     {1, true},
     {2, false},
     {3, true},
     {4, false},
     {5, true}
   });
  }
  @Test
  public void testisOdd() {
   System.out.println("Running test for:"+inputNumber);
   assertEquals(mathChecker.isOdd(inputNumber), expected);
  }
 }
테스트를 수행할 테스트 데이터는 getTestData() 방법으로 지정됩니다.이 방법은 하드 인코딩 데이터가 아니라 외부 파일에서 데이터를 읽는 것으로 쉽게 수정할 수 있다.
일곱Print 문구 대신 단언 사용
많은 초보 개발자들은 줄마다 코드를 작성한 후에 시스템을 작성하는 것에 익숙하다.out.println 문장은 코드가 정확하게 실행되었는지 확인합니다.이런 방법은 종종 단원 테스트로 확대되어 테스트 코드가 난잡해진다.혼란을 제외하고는 컨트롤러에 인쇄된 출력을 검증하기 위해 개발자가 수동으로 관여하여 테스트가 성공적으로 실행되었는지 확인해야 한다.더 좋은 방법은 테스트 결과를 자동으로 표시하는 단언을 사용하는 것이다.
다음 StringUti 클래스는 두 개의 입력 문자열을 연결하고 결과를 반환하는 간단한 클래스입니다.

public class StringUtil {
  public String concat(String a,String b) {
   return a + b;
  }
 }
다음은 상기 방법의 두 단원 테스트입니다.

@Test
 public void testStringUtil_Bad() {
   String result = stringUtil.concat("Hello ", "World");
   System.out.println("Result is "+result);
 }
 @Test
 public void testStringUtil_Good() {
   String result = stringUtil.concat("Hello ", "World");
   assertEquals("Hello World", result);
 }
testStringUtil\_Bad는 단언이 없기 때문에 항상 전달될 것입니다.개발자는 수동으로 컨트롤러에서 테스트의 출력을 검증해야 한다.만약 방법이 잘못된 결과를 되돌려 주고 개발자가 관여할 필요가 없다면, testStringUtil\_Good는 실패합니다.
여덟확실한 결과를 가진 테스트 구축
일부 방법은 확정적인 결과를 가지고 있지 않다. 즉, 이 방법의 출력은 미리 알고 있지 않고 매번 바뀔 수 있다.예를 들어, 다음과 같은 코드를 고려하면, 복잡한 함수와 복잡한 함수를 실행하는 데 필요한 시간(밀리초 단위)을 계산하는 방법이 있다.

public class DemoLogic {
 private void veryComplexFunction(){
  //This is a complex function that has a lot of database access and is time consuming
  //To demo this method, I am going to add a Thread.sleep for a random number of milliseconds
  try {
   int time = (int) (Math.random()*100);
   Thread.sleep(time);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
 public long calculateTime(){
  long time = 0;
  long before = System.currentTimeMillis();
  veryComplexFunction();
  long after = System.currentTimeMillis();
  time = after - before;
  return time;
 }
 }
이 경우,calculateTime 방법을 실행할 때마다 다른 값을 되돌려줍니다.이 방법을 위해 테스트 용례를 작성하는 것은 아무런 소용이 없다. 왜냐하면 이 방법의 출력은 가변적이기 때문이다.따라서 테스트 방법은 특정한 실행된 출력을 검증할 수 없습니다.
아홉긍정적인 상황 외에 부정적인 상황과 가장자리 상황도 테스트해야 한다
일반적으로 개발자들은 프로그램이 예상대로 작동하도록 하기 위해 테스트 용례를 작성하는 데 많은 시간과 정력을 들인다.그러나 부정적인 테스트 용례를 테스트하는 것도 중요하다.부정적인 테스트 용례는 테스트 시스템이 잘못된 데이터를 처리할 수 있는지의 테스트 용례를 가리킨다.예를 들어 간단한 함수를 고려하면 길이가 8인 알파벳 숫자 값을 읽을 수 있고 사용자가 입력할 수 있다.영숫자 값을 제외하고 다음과 같은 부정적인 테스트 용례를 테스트해야 한다.
  1. 사용자는 특수 문자와 같은 비 영숫자 값을 지정합니다.
  2. 사용자가 빈 값을 지정합니다.
  3. 사용자는 8자보다 크거나 작은 값을 지정합니다.
유사하게 경계 테스트 용례 테스트 시스템이 극단값에 적용되는지 여부.예를 들어 사용자가 1부터 100까지의 숫자 값을 입력하기를 원한다면 1과 100은 경계 값이므로 이 값을 테스트 시스템에 적용하는 것이 매우 중요하다.
이상은 본문의 전체 내용입니다. 본고의 내용이 여러분의 학습이나 업무에 일정한 도움을 줄 수 있는 동시에 저희를 많이 지지해 주시기 바랍니다!

좋은 웹페이지 즐겨찾기