문제

다음과 같은 단위 테스트를 수행할 수 있는 도구를 찾고 있습니다.

IPerson p = new Person();
p.Name = "Sklivvz";
Assert.AreEqual("Sklivvz", p.Name);

해당 스텁 클래스와 인터페이스를 자동으로 생성합니다.

interface IPerson         // inferred from IPerson p = new Person();
{
    string Name 
    { 
        get;              // inferred from Assert.AreEqual("Sklivvz", p.Name);
        set;              // inferred from p.Name = "Sklivvz";
    }
}

class Person: IPerson     // inferred from IPerson p = new Person();
{
    private string name;  // inferred from p.Name = "Sklivvz";

    public string Name    // inferred from p.Name = "Sklivvz";
    {
        get
        {
            return name;  // inferred from Assert.AreEqual("Sklivvz", p.Name);
        }
        set
        {
            name = value; // inferred from p.Name = "Sklivvz";
        }
    }

    public Person()       // inferred from IPerson p = new Person();
    {
    }
}

ReSharper와 Visual Studio가 이들 중 일부를 수행한다는 것을 알고 있지만 수행해야 할 작업을 자동으로 추론하는 완전한 도구(명령줄 등)가 필요합니다.그러한 도구가 없다면 어떻게 작성하시겠습니까(예:어떤 라이브러리를 사용하여 처음부터 ReSharper를 확장하시겠습니까?

도움이 되었습니까?

해결책

필요한 것은 언어(Java)에 대한 파서와 이름 및 유형 확인자입니다.("심볼 테이블 빌더").

소스 텍스트를 구문 분석한 후 컴파일러에는 일반적으로 이름 정의와 해당 유형을 기록하려고 시도하는 이름 확인기와 각 표현식에 유효한 유형이 있는지 확인하는 유형 검사기가 있습니다.

일반적으로 이름/유형 확인자는 정의를 찾을 수 없을 때 불평합니다.당신이 원하는 것은 문제를 일으키는 "정의되지 않은" 것을 찾아 그에 대한 유형을 추론하는 것입니다.

을 위한

 IPerson p = new Person();

이름 확인자는 "Person"과 "IPerson"이 정의되지 않았다는 것을 알고 있습니다.그렇다면

 Foo  p =  new Bar();

Foo가 Bar의 일종의 추상 부모(예: 클래스 또는 인터페이스)라는 것 외에는 인터페이스를 원했다는 단서가 없습니다.따라서 어떤 결정이 도구에 알려져야 합니다("이러한 구성을 찾을 때마다 Foo가 인터페이스라고 가정합니다...").경험적 방법을 사용할 수 있습니다.IFoo와 Foo는 IFoo가 인터페이스여야 하고 누군가가 Foo를 해당 인터페이스를 구현하는 클래스로 정의해야 함을 의미합니다.도구 가이 결정을 내린 후에는 기호 테이블을 업데이트하여 다른 문장으로 이동할 수 있도록해야합니다.

을 위한

 p.Name = "Sklivvz";

p가 인터페이스(이전 추론에 따라)여야 하는 경우 Name은 필드 멤버여야 하며 해당 유형은 할당의 문자열인 것으로 나타납니다.

이에 대한 진술은 다음과 같습니다.

 Assert.AreEqual("Sklivvz", p.Name);

이름과 유형은 추가 문제 없이 해결됩니다.

IFoo 및 Foo 엔터티의 내용은 사용자에게 달려 있습니다.get과 set을 사용할 필요는 없지만 그것은 개인적인 취향입니다.

동일한 명령문에 여러 엔터티가 있는 경우에는 제대로 작동하지 않습니다.

 x = p.a + p.b ;

a와 b가 필드일 가능성이 높다는 것을 알고 있지만 실제로 숫자인지 또는 문자열인지는 어떤 숫자 유형인지 추측할 수 없습니다(Java에서는 문자열에 적합하지만 C#에 대해서는 모릅니다).C++의 경우 "+"가 무엇을 의미하는지조차 모릅니다.Bar 클래스의 연산자일 수 있습니다.그래서 당신이 해야 할 일은 수집하는 것입니다 제약, 예를 들어 "a는 불확실한 숫자 또는 문자열입니다." 등도구가 증거를 수집함에 따라 가능한 제약 조건의 범위가 좁아집니다.(이것은 단어 문제와 유사하게 작동합니다.“조에게는 일곱 명의 아들이 있어요.제프는 샘보다 키가 더 크다.해리는 샘 뒤에 숨을 수 없어요....Jeff의 쌍둥이는 누구입니까?" 증거를 수집하고 불가능한 것을 제거해야 합니다.)모순으로 끝나는 경우도 걱정해야합니다.

p.a+p.b 사례를 배제할 수 있지만, 그러면 처벌 없이 단위 테스트를 작성할 수 없습니다.면책을 원한다면 표준 제약 해결사가 있습니다.(이런 컨셉이군요).

좋아요, 이제 아이디어가 생겼습니다. 이것이 실제적인 방법으로 이루어질 수 있을까요?

첫 번째 부분에는 파서와 구부릴 수 있는 이름 및 유형 확인자가 필요합니다.제약 조건 해결 프로그램이 필요하거나 최소한 "정의된 값이 정의되지 않은 값으로 흐른다" 작업(사소한 제약 조건 해결 프로그램)이 필요합니다.

우리의 DMS 소프트웨어 리엔지니어링 툴킷 그것으로 자바 프런트엔드 아마도 이렇게 할 수 있을 것입니다.DMS는 컴퓨터 언어를 임의의 방식으로 처리하는 도구를 만들고자 하는 사람들을 위한 도구 제작자의 도구입니다.("숫자보다는 프로그램 조각으로 계산하는 것"을 생각해 보세요).

DMS는 범용 구문 분석 기계를 제공하며 주어진 프런트엔드(예: Java 및 C# 프런트엔드)에 대한 트리를 구축할 수 있습니다.내가 Java를 선택한 이유는 Java 프런트 엔드에 이름 및 유형 확인 기능이 모두 있고 소스 형식으로 제공되므로 구부릴 수 있기 때문입니다.사소한 제약 조건 해결 프로그램을 고수했다면 아마도 Java 이름 확인 프로그램을 구부려 유형을 파악할 수 있을 것입니다.DMS를 사용하면 코드 조각에 해당하는 트리를 모아 더 큰 조각으로 통합할 수 있습니다.도구가 기호 테이블에 대한 정보를 수집하면 기본 트리를 구축할 수 있습니다.

어딘가에서 끝났다고 결정해야 합니다.전체 인터페이스를 알기 전에 도구가 볼 수있는 단위 테스트는 몇 개입니까?(당신이 제공한 모든 것을 먹는 것 같아요?).완료되면 다양한 구성원에 대한 조각을 조립하고 인터페이스에 대한 AST를 구축합니다.DMS는 Prettyprinter를 사용하여 표시된 대로 해당 AST를 소스 코드로 다시 변환할 수 있습니다.

Java 프런트엔드에는 이름 및 유형 확인 기능이 있으므로 여기서는 Java를 제안합니다.우리의 C# 프런트엔드는 그렇지 않습니다.이것은 야망의 "단순한" 문제입니다.누군가는 작성해야 하지만 이는 꽤 많은 작업입니다(적어도 Java용이었고 C#이 실제로 다를 것이라고는 상상할 수 없습니다).

그러나 이 아이디어는 원칙적으로 DMS를 사용하면 잘 작동합니다.

파서와 구부릴 수 있는 이름 및 유형 확인자에 대한 액세스를 제공하는 다른 인프라를 사용하여 이 작업을 수행할 수 있습니다.C#에서는 얻기가 쉽지 않을 수 있습니다.MS가 파서와 이름 및 유형 확인에 대한 액세스 권한을 제공할 수 있지만 이를 변경할 수 있는 방법은 없을 것으로 생각됩니다.어쩌면 모노가 답일까요?

코드 조각을 생성하고 조합하려면 여전히 was가 필요합니다.문자열 해킹을 통해 이를 시도할 수도 있습니다.프로그램 비트를 함께 붙이는 것에 대한 나의 (오랜) 경험은 문자열을 사용하여 수행하면 결국 엉망이 된다는 것입니다.당신은 문법이 허용하는 방식으로만 결합될 수 있는 알려진 유형의 코드 조각을 나타내는 조각을 정말로 원합니다.DMS는 이를 수행하므로 혼란스럽지 않습니다.

다른 팁

당신이 요청한 것에 대해 아무도 실제로 아무것도 제공하지 않았다는 사실이 놀랍습니다.

답은 모르겠지만, 제 생각을 말씀드리겠습니다.

내가 이와 같은 것을 직접 작성하려고 시도한다면 아마도 resharper 플러그인에 대해 알게 될 것입니다.제가 그렇게 말하는 이유는 말씀하신 대로 ReSharper가 이를 수행할 수 있지만 개별 단계에서 수행할 수 있기 때문입니다.그래서 저는 한 줄씩 연결되어 적절한 리샤퍼 생성 방법을 적용한 내용을 작성했습니다.

나는 resharper를 위한 어떤 것도 구축한 적이 없기 때문에 이 작업을 수행하는 방법조차 알지 못하지만 그것이 제가 하려고 하는 것입니다.그것이 가능하다는 것이 논리적으로 타당하다.

그리고 코드를 작성한다면 게시해 주세요. 한 단계로 전체 뼈대를 생성할 수 있어서 유용할 수도 있습니다.굉장히 유용하다.

자신만의 구현을 작성할 계획이라면 다음을 살펴보는 것이 좋습니다. N속도 (C#) 또는 속도 (Java) 템플릿 엔진.

나는 이전에 코드 생성기에서 이것을 사용해 본 적이 있으며 작업이 훨씬 더 쉬워진다는 것을 알았습니다.

적어도 이론적으로는 가능합니다.내가 할 일은 다음과 같은 것을 사용하는 것입니다. csparser 단위 테스트를 구문 분석한 다음(안타깝게도 컴파일할 수 없음) 거기에서 가져옵니다.내가 볼 수 있는 유일한 문제는 당신이 하고 있는 일이 방법론 측면에서 잘못되었다는 것입니다. 엔터티 클래스에서 단위 테스트를 생성하는 것이 반대 방법으로 수행하는 것보다(실제로 Visual Studio에서 정확하게 이 작업을 수행함) 더 합리적입니다.

나는 이 문제에 대한 진정한 해결책은 매우 전문적인 파서가 될 것이라고 생각합니다.그게 쉽지가 않아서 좀 더 저렴한 아이디어가 있어요.불행하게도 테스트 작성 방법(즉, 객체 생성 방법)을 변경해야 합니다.

dynamic p = someFactory.Create("MyNamespace.Person");
p.Name = "Sklivvz";
Assert.AreEqual("Sklivvz", p.Name);

팩토리 객체가 사용됩니다.명명된 개체를 찾을 수 있으면 해당 개체를 만들고 반환합니다(이것이 일반적인 테스트 실행입니다).찾지 못하면 녹음 프록시( DynamicObject)는 모든 호출을 기록하고 마지막에(아마도 해체 시) 호출되는 것을 "본" 내용을 반영하는 클래스 파일(일부 템플릿을 기반으로 할 수도 있음)을 내보낼 수 있습니다.

제가 생각하는 몇 가지 단점은 다음과 같습니다.

  • "2가지" 모드에서 코드를 실행해야 하는데, 이는 짜증나는 일입니다.
  • 프록시가 통화를 "보고" 녹음하려면 프록시를 실행해야 합니다.그래서 코드를 catch 예를 들어 블록이 실행되어야 합니다.
  • 테스트 대상 개체를 생성하는 방식을 변경해야 합니다.
  • 당신은 사용해야합니다 dynamic;후속 실행에서는 컴파일 타임 안전성을 잃게 되며 성능이 저하됩니다.

제가 볼 때 유일한 장점은 훨씬 저렴하다 전문적인 파서보다 생성합니다.

저는 DevExpress의 CodeRush를 좋아합니다.그들은 사용자 정의가 가능한 거대한 템플릿 엔진을 가지고 있습니다.그리고 저에게 가장 좋은 점은 대화 상자가 없다는 것입니다.또한 존재하지 않는 인터페이스에서 메서드와 인터페이스, 클래스를 생성하는 기능도 있습니다.

아직 연구 중인 Microsoft의 단위 테스트 프로젝트인 Pex를 살펴보세요.

Research.microsoft.com/en-us/projects/Pex/

당신이 찾고 있는 것은 퍼징 툴킷(https://en.wikipedia.org/wiki/Fuzz_testing)인 것 같습니다.

내가 한 번도 사용해본 적이 없지만 Randoop.NET에 '단위 테스트'를 생성할 기회를 줄 수도 있습니다. http://randoop.codeplex.com/

Visual Studio에는 여기에서 도움이 될 수 있는 몇 가지 기능이 포함되어 있습니다.

메소드 스텁 생성.존재하지 않는 메서드에 대한 호출을 작성하면 메서드 이름에 작은 스마트 태그가 표시되며, 이를 사용하여 전달하는 매개 변수를 기반으로 메서드 스텁을 생성할 수 있습니다.

당신이 키보드 사용자라면(저는 그렇습니다) 닫는 괄호를 입력한 직후에 다음을 수행할 수 있습니다.

  • Ctrl 키-. (스마트 태그 열기)
  • 입력하다 (스텁을 생성하기 위해)
  • F12 (정의로 이동하여 새 방법으로 이동)

스마트 태그는 IDE에서 일치하는 메서드가 없다고 판단하는 경우에만 나타납니다.스마트 태그가 작동되지 않을 때 생성하려면 다음으로 이동하세요. 편집->Intellisense->메서드 스텁 생성.

짧은 발췌.일반적인 코드를 쉽게 생성할 수 있는 작은 코드 템플릿입니다.일부는 간단합니다("if[TAB][TAB]"를 시도해 보세요).일부는 복잡합니다('스위치'는 열거형에 대한 사례를 생성합니다).직접 작성할 수도 있습니다.귀하의 경우에는 "class"와 "prop"을 사용해보십시오.

또한보십시오 "VS에서 NotImplementedException을 발생시키도록 "메소드 스텁 생성"을 변경하는 방법은 무엇입니까?" GMS 맥락에서 정보 스니펫을 확인하세요.

자동소품.속성이 훨씬 간단할 수 있다는 점을 기억하세요.

public string Name { get; set; }

수업 만들기.솔루션 탐색기에서 프로젝트 이름이나 하위 폴더를 R클릭하고 추가->클래스.새 수업의 이름을 입력하세요.때리다 입력하다.올바른 네임스페이스 등에서 클래스 선언을 얻게 됩니다.

인터페이스 구현.클래스가 인터페이스를 구현하도록 하려면 인터페이스 이름 부분을 작성하고 스마트 태그를 활성화한 다음 인터페이스 멤버에 대한 스텁을 생성하는 옵션 중 하나를 선택합니다.

이는 귀하가 찾고 있는 100% 자동화된 솔루션은 아니지만 좋은 완화책이라고 생각합니다.

이와 같은 코드 생성 도구가 필요할 때마다 좀 더 일반적인 코드를 작성하게 되므로 한 번만 작성하면 됩니다.귀하의 예에서 해당 getter 및 setter는 코드에 값을 추가하지 않는 것 같습니다. 실제로는 C#의 getter/setter 메커니즘이 작동한다고 주장하는 것뿐입니다.

나는 이러한 종류의 테스트를 작성하는 동기가 무엇인지 이해하기 전에는 그러한 도구를 작성(또는 사용)하지 않을 것입니다.

그런데, 당신은 한 번보고 싶을 수도 있습니다 NBehave?

저는 간단한 스텁이 필요할 때 Rhino Mocks를 사용합니다.

http://www.ayende.com/wiki/Rhino+Mocks+-+Stubs.ashx

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top