programing

정규식을 어떻게 단위 테스트합니까?

coolbiz 2021. 1. 18. 08:14
반응형

정규식을 어떻게 단위 테스트합니까?


저는 TDD를 처음 접했고 RegExp가 아주 특별한 경우라고 생각합니다. 단위 테스트를위한 특별한 방법이 있습니까? 아니면 일반 함수로 취급 할 수 있습니까?


다른 코드 덩어리와 마찬가지로 항상 정규식을 테스트해야합니다. 문자열을 받아 bool을 반환하거나 값의 배열을 반환하는 가장 단순한 함수입니다.

다음은 regexen에 대한 단위 테스트를 설계 할 때 고려해야 할 몇 가지 제안 사항입니다. 이것은 단위 테스트 디자인에 대한 어렵고 빠른 처방이 아니라 생각을 형성하는 몇 가지 지침입니다. 항상 그렇듯이 테스트 요구 사항과 실패 비용의 균형을 모두 구현하는 데 필요한 시간과 비교하십시오. (테스트를 '구현'하는 것이 쉬운 부분이라는 것을 알았습니다! :-])

고려할 사항 :

  • 모든 그룹 (괄호)을 중괄호로 생각하십시오.
  • 모든 생각 | 조건으로. 각 분기에 대해 테스트하십시오.
  • 모든 수정 자 (*, +,?)를 다른 경로로 생각하십시오.
  • (위에 대한 참고 사항 : *, +,? 및 * ?, +? 및 ??의 차이점을 기억하십시오.)
  • \ d, \ s, \ w 및 그 부정에 대해 각 범위에서 여러 번 시도해보십시오.
  • * 및 +의 경우 각각에 대해 '값 없음', '하나 중'및 '하나 이상'을 테스트해야합니다.
  • 중요한 '제어'문자 (예 : 찾는 정규식의 문자열)의 경우 잘못된 위치에 표시되면 어떻게되는지 테스트합니다. 이것은 당신을 놀라게 할 수 있습니다.
  • 실제 데이터가있는 경우 가능한 한 많이 사용하십시오.
  • 그렇지 않은 경우 유효해야하는 단순 양식과 복잡한 양식을 모두 테스트해야합니다.
  • 삽입시 정규식 제어 문자가 수행하는 작업을 테스트해야합니다.
  • 빈 문자열이 제대로 허용 / 거부되었는지 확인하십시오.
  • 각기 다른 종류의 공백 문자의 문자열이 올바르게 허용 또는 거부되는지 확인하십시오.
  • 대소 문자 구분이 적절하지 않은지 확인하십시오 (i 플래그). 이것은 텍스트 구문 분석 (공백 제외)에서 거의 다른 것보다 나를 더 많이 물었습니다.
  • x, m 또는 s 옵션이있는 경우 해당 옵션이 수행하는 작업을 이해하고 테스트해야합니다 (여기서 동작은 다를 수 있음).

목록을 반환하는 정규식의 경우 다음 사항도 기억하세요.

  • 예상 한 데이터가 올바른 필드에 올바른 순서로 반환되는지 확인합니다.
  • 약간의 수정이 좋은 데이터를 반환하지 않는지 확인하십시오.
  • 혼합 된 익명 그룹과 명명 된 그룹이 올바르게 구문 분석되는지 확인합니다 (예 :). (?<name> thing1 ( thing2) )이 동작은 사용중인 정규식 엔진에 따라 다를 수 있습니다.
  • 다시 한 번 실제 세계에서 많은 시도를하세요.

비 역 추적 그룹과 같은 고급 기능을 사용하는 경우 기능이 작동하는 방식을 완전히 이해하고 위의 지침을 사용하여 각각에 대해 작동해야하는 예제 문자열을 작성하십시오.

정규식 라이브러리 구현에 따라 그룹이 캡처되는 방식도 다를 수 있습니다. Perl 5에는 'open paren order'순서가 있으며 C #에는 명명 된 그룹 등을 제외하고 부분적으로 있습니다. 그것이 무엇을하는지 정확히 알기 위해 당신의 맛을 시험해보십시오.

그런 다음 자체 모듈에서 또는 정규식을 포함하는 모듈과 함께 다른 단위 테스트에 바로 통합합니다. 특히 불쾌한 정규식의 경우 사용하는 패턴과 모든 기능이 올바른지 확인하기 위해 많은 테스트가 필요할 수 있습니다. 정규식이 메서드가 수행하는 작업의 큰 (또는 거의 모든)을 구성하는 경우 위의 조언을 사용하여 입력을 패션화하여 정규식이 아닌 해당 함수를 테스트 할 것입니다. 이렇게하면 나중에 정규식을 사용할 방법이 아니라고 결정하거나 분할하려는 경우 인터페이스 (예 : 정규식을 호출하는 메서드)를 변경하지 않고 정규식이 제공 한 동작을 캡처 할 수 있습니다.

정규식 기능이 정규식에서 작동하는 방식을 실제로 알고있는 한, 적절한 테스트 케이스를 개발할 수 있어야합니다. 기능이 어떻게 작동하는지 정말, 정말, 정말로 이해하고 있는지 확인하십시오!


여러 값을 던져서 올바른 결과를 얻었는지 확인하십시오 (일치 / 불일치 또는 특정 대체 값 등).

중요한 것은 그들이 작동하는지 아닌지 궁금한 코너 케이스가 있다면 단위 테스트에서 캡처하고 작동 이유주석으로 설명하십시오 . 이렇게하면 정규식을 변경하려는 다른 사람이 코너 케이스가 여전히 작동하는지 확인할 수 있으며, 고장난 경우이를 수정하는 방법에 대한 힌트를 제공 할 것입니다.


아마도 정규식은 클래스의 메서드 내에 포함되어있을 것입니다. 예를 들면 :

public bool ValidateEmailAddress( string emailAddr )
{
    // Validate the email address using regular expression.
    return RegExProvider.Match( this.ValidEmailRegEx, emailAddr );
}

이제이 메서드에 대한 테스트를 작성할 수 있습니다. 요점은 정규식이 구현 세부 사항이라는 것입니다. 테스트는 인터페이스를 테스트해야합니다.이 경우에는 이메일 유효성 검사 방법 일뿐입니다.


다른 모든 테스트 사례와 마찬가지로 예상 출력 값으로 입력 값 집합을 만듭니다.

또한 무료 Regex Tool Expresso를 철저히 추천 할 수 있습니다 . 과거에 고통의 날을 구해준 환상적인 정규식 편집기 / 디버거입니다.


다른 기능을 수행하는 것처럼 항상 테스트합니다. 일치해야한다고 생각하는 것과 일치해서는 안되는 것과 일치하지 않는지 확인하십시오.


아무도이 놀라운 도구를 게시하지 않았다는 것을 믿을 수 없습니다.

refiddle.com

정규식을 테스트 할 수 있습니다. 일치해야하는 문자열을 포함하는 텍스트를 정의하고 일치하지 않아야하는 문자열을 정의하고 모두 녹색이면 괜찮습니다. 예를 들어 다음은 슬러그와 일치하도록 만든 것입니다. http://refiddle.com/by/callum-locke/slug-matcher


간단한 입력 출력 테스트로 충분하다고 생각합니다. 시간이 지남에 따라 정규식이 실패하는 경우가 발생하면 이러한 경우를 수정하는 동안 테스트에 추가하는 것을 잊지 마십시오.


저는 반대 정규 표현식에 대해 정규 표현식을 테스트하고 싶습니다. 가능한 테스트에 대해 둘 다 실행하고 교차가 비어 있는지 확인합니다.


먼저 테스트를 작성하고 각 테스트를 통과하는 데 필요한만큼만 정규 표현식을 작성하는 것이 좋습니다. 정규 표현식을 확장해야하는 경우 실패한 테스트를 추가하여 수행하십시오.


선택한 단위 테스트 라이브러리에서 픽스처를 사용하고 일반적인 TDD 접근 방식을 따릅니다.

  • 확인 : 테스트가 녹색입니다.
  • 다음 "기능"에 대한 테스트를 추가하여 테스트 중단
  • 정규식을 조정하여 녹색으로 만듭니다 (기존 테스트를 중단하지 않고).
  • 더 나은 가독성을 위해 정규식 리팩터링 (예 : 명명 된 그룹, 문자 범위 대신 문자 클래스 등)

다음은 테스트 실행기 인 spock에 대한 샘플 픽스처 스텁입니다.

@Grab('org.spockframework:spock-core:1.3-groovy-2.5')
@GrabExclude('org.codehaus.groovy:groovy-nio')
@GrabExclude('org.codehaus.groovy:groovy-macro')
@GrabExclude('org.codehaus.groovy:groovy-sql')
@GrabExclude('org.codehaus.groovy:groovy-xml')

import spock.lang.Unroll

class RegexSpec extends spock.lang.Specification {
  String REGEX = /[-+]?\d+(\.\d+)?([eE][-+]?\d+)?/

  @Unroll
  def 'matching example #example for case "#description" should yield #isMatchExpected'(String description, String example, Boolean isMatchExpected) {
    expect:
    isMatchExpected == (example ==~ REGEX)

    where:
    description                                  | example        || isMatchExpected
    "empty string"                               | ""             || false
    "single non-digit"                           | "a"            || false
    "single digit"                               | "1"            || true
    "integer"                                    | "123"          || true
    "integer, negative sign"                     | "-123"         || true
    "integer, positive sign"                     | "+123"         || true
    "float"                                      | "123.12"       || true
    "float with exponent extension but no value" | "123.12e"      || false
    "float with exponent"                        | "123.12e12"    || true
    "float with uppercase exponent"              | "123.12E12"    || true
    "float with non-integer exponent"            | "123.12e12.12" || false
    "float with exponent, positive sign"         | "123.12e+12"   || true
    "float with exponent, negative sign"         | "123.12e-12"   || true
  }
}

다음과 같은 독립 실행 형 그루비 스크립트로 실행할 수 있습니다.

groovy regex-test.groovy

면책 조항 : 스 니펫은 내가 몇 주 전에 작성한 일련의 블로그 게시물에서 가져온 것입니다.

참조 URL : https://stackoverflow.com/questions/488601/how-do-you-unit-test-regular-expressions

반응형