2014-02-16 176 views
2

我想定義匹配器來檢查分析器是否可以接受字符串。我做到了,但感覺不好。爲單元測試定義「accept」和「notAccept」匹配的更好方法

飛鏢單元測試代碼:

library test_parser; 

import 'package:unittest/unittest.dart'; 
import '../lib/shark_parser.dart'; 

main() { 
    SharkParser parser; 
    setUp(() { 
    parser = new SharkParser(); 
    }); 
    tearDown(() { 
    parser = null; 
    }); 

    group("paramType parser",() { 
    test("should accept valid types",() { 
     expect(parser.paramType(), accept("String")); 
     expect(parser.paramType(), accept("int")); 
     expect(parser.paramType(), accept("List")); 
     expect(parser.paramType(), accept("List<User>")); 
    }); 
    test("should not accept invalid types",() { 
     expect(parser.paramType(), notAccept("#")); 
     expect(parser.paramType(), notAccept("0")); 
     expect(parser.paramType(), notAccept("String()")); 
     expect(parser.paramType(), notAccept("List<User>")); 
    }); 
    }); 
} 

的匹配器:

Matcher accept(String matchingString) => new AcceptMatcher(matchingString); 

Matcher notAccept(String matchingString) => new NotAcceptMatcher(matchingString); 

class NotAcceptMatcher extends Matcher { 
    String matchingString; 

    NotAcceptMatcher(this.matchingString); 

    bool matches(item, Map matchState) { 
    return !item.end().accept(matchingString); 
    } 

    Description describe(Description description) { 
    return description.add("parser not accept string: $matchingString"); 
    } 

    Description describeMismatch(item, Description mismatchDescription, 
           Map matchState, bool verbose) { 
    mismatchDescription.add("accepts it"); 
    return mismatchDescription; 
    } 
} 

class AcceptMatcher extends Matcher { 

    String matchingString; 

    AcceptMatcher(this.matchingString); 

    bool matches(item, Map matchState) { 
    return item.end().accept(matchingString); 
    } 

    Description describe(Description description) { 
    return description.add("parser accept string: $matchingString"); 
    } 

    Description describeMismatch(item, Description mismatchDescription, 
           Map matchState, bool verbose) { 
    mismatchDescription.add("doesn't accept"); 
    return mismatchDescription; 
    } 

} 

你可以看到我有定義兩個匹配器NotAcceptMatcherAcceptMatcher。邏輯非常相似,但我不知道如何簡化。

有沒有其他更簡單的解決方案來做到這一點?

回答

2

可以使用isNot匹配即可反轉accept匹配:

expect(parser.paramType(), isNot(accept("#"))); 

它讀取有點滑稽,所以你可以創建一個函數來做到這一點:

Matcher notAccept(String s) => isNot(accept(s)); 

expect(parser.paramType(), notAccept("#")); 

的描述可能不完美閱讀,但它可以節省一些工作。

匹配器可能看起來很冗長,但是如果你想要的話,你可以通過刪除一些類型的註釋和使用短變量名來使你的匹配器定義更簡潔一些。當我寫一個由框架調用的類或函數時,我覺得這是一個好的折衷,因爲我不擔心爲其他用戶記錄它。

class AcceptMatcher extends Matcher { 
    final acceptString; 

    AcceptMatcher(this.acceptString); 

    matches(item, _) => item.end().accept(acceptString); 

    describe(d) => d.add("parser accept string: $acceptString"); 

    describeMismatch(item, d, _, __) => d..add("doesn't accept"); 
} 

另一種選擇是隻使用predicate匹配:

Matcher accept(String s) => 
    predicate((i) => i.end().accept(s), "parser accepts $s");