Upgrade to Pro — share decks privately, control downloads, hide ads and more …

テスト駆動開発基本編

 テスト駆動開発基本編

テスト駆動開発について解説します。なるべく書籍に書いてない内容を盛り込みました。まず基本的な内容から。その他編に続きます。

まりも

May 16, 2024
Tweet

More Decks by まりも

Other Decks in Programming

Transcript

  1. レッド [Test] public void 指定したPathがプロパティとして取得できます() { var tested = new

    CssFile(@"C:¥File1.css"); Expect(tested.Path, Is.EqualTo(@"C:¥File1.css")); }
  2. public string Path { get; } public string Path {

    get { return @"C:¥File1.css"; } } グリーン
  3. レッド [Test] public void 指定したPathがプロパティとして取得できます() { var tested = new

    CssFile(@"C:¥File1.css"); Expect(tested.Path, Is.EqualTo(@"C:¥File1.css")); } public void 指定したPathがプロパティとして取得できます() { var tested = new CssFile(@"C:¥File1.css"); Expect(tested.Path, Is.EqualTo(@"C:¥File1.css")); var tested2 = new CssFile(@"C:¥File2.css"); Expect(tested2.Path, Is.EqualTo(@"C:¥File2.css")); }
  4. public string Path { get; set; } public CssFile(string path)

    { Path = path; } public string Path { get { return @"C:¥File1.css"; } } public CssFile(string path) { } グリーン
  5. レッド [Test] public void ToStringで基本的なCSSの出力ができます() { var tested = new

    CssStatement(); tested.Selectors = new[] { "H1" }; tested.Declarations = new Dictionary<string, string> { { "font-size", "12pt" } }; Expect(tested.ToString(), Is.EqualTo( @"H1 { font-size: 12pt }")); }
  6. public Dictionary<string, string> Declarations { get; set; } public string[]

    Selectors { get; set; } public override string ToString() { return @"H1 { font-size: 12pt }"; } グリーン public Dictionary<string, string> Declarations { get; set; } public string[] Selectors { get; set; }
  7. [Test] public void ToStringでセレクタの種類を見分けて出力に反映します() { var tested = new CssStatement();

    tested.Selectors = new[] { "H2" }; tested.Declarations = new Dictionary<string, string> { { "font-size", "12pt" } }; Expect(tested.ToString(), Is.EqualTo( @"H2 { font-size: 12pt }")); } レッド
  8. レッド public void ToStringで複数のセレクタを出力に反映します() { var tested = new CssStatement();

    tested.Selectors = new[] { "H1", "H2" }; tested.Declarations = new Dictionary<string, string> { { "font-size", "12pt" } }; Expect(tested.ToString(), Is.EqualTo( @"H1, H2 { font-size: 12pt }")); }
  9. public override string ToString() { return $@"{string.Join(", ",Selectors)} {{ font-size:

    12pt }}"; } リファクタ リング public override string ToString() { return $@"{CssForSelectors()} {{ font-size: 12pt }}"; } private string CssForSelectors() { return string.Join(", ", Selectors); }
  10. [Test] public void ToStringでプロパティの種類を出力に反映します() { var tested = new CssStatement();

    tested.Selectors = new[] { "H1", "H2" }; tested.Declarations = new Dictionary<string, string> { { "line-height", "12pt" } }; Expect(tested.ToString(), Is.EqualTo( @"H1, H2 { line-height: 12pt }")); } レッド
  11. [Test] public void ToStringで値を見て出力に反映します() { var tested = new CssStatement();

    tested.Selectors = new[] { "H1", "H2" }; tested.Declarations = new Dictionary<string, string> { { "line-height", "10pt" } }; Expect(tested.ToString(), Is.EqualTo( @"H1, H2 { line-height: 10pt }")); } レッド
  12. [Test] public void ToStringで複数の特性を出力に反映します() { var tested = new CssStatement();

    tested.Selectors = new[] { "H1", "H2" }; tested.Declarations = new Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } }; Expect(tested.ToString(), Is.EqualTo( @"H1, H2 { font-size: 12pt; line-height: 10pt }")); } レッド
  13. public override string ToString() { return $@"{CssForSelectors()} {{ {CssForDeclarationCollection()} }}";

    } private string CssForDeclarationCollection() { return string.Join(";¥r¥n ", Declarations.Select(delaration => CssForDeclaration(delaration))); } public override string ToString() { return $@"{CssForSelectors()} {{ {string.Join(";¥r¥n ", Declarations.Select(delaration => CssForDelaration(delaration)))} }}"; } リファクタ リング
  14. private string CssForDelaration(KeyValuePair<string, string> delaration) { return $"{delaration.Key}: {delaration.Value}"; }

    private string CssForDelarationCollection() { return string.Join(";¥r¥n ", from delaration in Declarations select CssForDelaration(delaration)); } private string CssForDelarationCollection() { return string.Join(";¥r¥n ", from delaration in Declarations select $"{delaration.Key}: {delaration.Value}"); } リファクタ リング
  15. [Test] public void ヘルパーを使ってCssが組み立てられます() { var tested = "H1".Css( font_size

    => "12pt", line_height => "10pt"); Expect(tested.ToString(), Is.EqualTo( @"H1 { font-size: 12pt; line-height: 10pt }")); } レッド
  16. using CssWriter.Helpers; namespace CssWriter.Helpers { public static class ExtensionsForCssWriter {

    public static CssStatement Css( this string selector, params Func<string, string>[] decdeclarations) { return null; } } } レッド
  17. var ret = new CssStatement(); ret.Selectors = new[] { "H1"

    }; ret.Declarations = new Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } }; return ret; グリーン return null;
  18. リファクタ リング return new CssStatement { Selectors = new[] {

    "H1" }, Declarations = new Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } } }; var ret = new CssStatement(); ret.Selectors = new[] { "H1" }; ret.Declarations = new Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } }; return ret;
  19. [Test] public void Helperを使ったCssの組み立てではセレ クターの種類を反映します() { var tested = "H2".Css(

    font_size => "12pt", line_height => "10pt"); Expect(tested.ToString(), Is.EqualTo( @"H2 { font-size: 12pt; line-height: 10pt }")); } レッド
  20. return new CssStatement { Selectors = new[] { selector },

    Declarations = new Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } } }; グリーン return new CssStatement { Selectors = new[] { "H1" }, Declarations = new Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } } };
  21. [Test] public void Helperを使ったCssの組み立てでは複数 のセレクターが指定できます() { var tested = new[]

    { "H1", "H2" }.Css( font_size => "12pt", line_height => "10pt"); Expect(tested.ToString(), Is.EqualTo( @"H1, H2 { font-size: 12pt; line-height: 10pt }")); } レッド
  22. return new CssStatement { Selectors = selector, Declarations = new

    Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } } }; グリーン return null;
  23. リファクタ リング public static CssStatement Css(this IEnumerable<string> selector, params Func<string,

    string>[] declarations) { return new CssStatement { Selectors = selector.ToArray(), Declarations = new Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } } }; } public static CssStatement Css(this string[] selector, params Func<string, string>[] declarations) { return new CssStatement { Selectors = selector, Declarations = new Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } } }; }
  24. リファクタ リング public static CssStatement Css(this string selector, params Func<string,

    string>[] declarations) { return Css(new[] { selector }, declarations); } public static CssStatement Css(this IEnumerable<string> selector, params Func<string, string>[] declarations) { return new CssStatement { Selectors = selector.ToArray(), Declarations = new Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } } }; } public static CssStatement Css(this string selector, params Func<string, string>[] decdeclarations) { return new CssStatement { Selectors = new[] { selector }, Declarations = new Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } } }; } public static CssStatement Css(this IEnumerable<string> selector, params Func<string, string>[] decdeclarations) { return new CssStatement { Selectors = selector.ToArray(), Declarations = new Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } } }; }
  25. [Test] public void Helperを使ったCssの組み立てでは特性を反映します() { var tested = "H2".Css( line_height

    => "12pt", font_size => "10pt"); Expect(tested.ToString(), Is.EqualTo( @"H2 { line-height: 12pt; font-size: 10pt }")); } レッド
  26. グリーン public static CssStatement Css(this string selector, params Expression<Func<string, string>>[]

    declarations) { return Css(new[] { selector }, declarations); } public static CssStatement Css(this IEnumerable<string> selector, params Expression<Func<string, string>>[] declarations) { return new CssStatement { Selectors = selector.ToArray(), Declarations = new Dictionary<string, string> { {declarations[0].Parameters.Single().Name.Replace('_', '-'), "12pt" }, {declarations[1].Parameters.Single().Name.Replace('_', '-'), "10pt" } } }; } public static CssStatement Css(this string selector, params Func<string, string>[] declarations) { return Css(new[] { selector }, declarations); } public static CssStatement Css(this IEnumerable<string> selector, params Func<string, string>[] declarations) { return new CssStatement { Selectors = selector.ToArray(), Declarations = new Dictionary<string, string> { {"font-size", "12pt" }, {"line-height", "10pt" } } }; }
  27. return new CssStatement { Selectors = selector.ToArray(), Declarations = new

    Dictionary<string, string> { {GetParameterName(declarations[0]), "12pt" }, {declarations[1].Parameters.Single().Name.Replace('_', '-'), "10pt" } } }; return new CssStatement { Selectors = selector.ToArray(), Declarations = new Dictionary<string, string> { {declarations[0].Parameters.Single().Name.Replace('_', '-'), "12pt" }, {declarations[1].Parameters.Single().Name.Replace('_', '-'), "10pt" } } }; リファクタ リング
  28. リファクタ リング return new CssStatement { Selectors = selector.ToArray(), Declarations

    = new Dictionary<string, string> { {GetParameterName(declarations[0]), "12pt" }, {GetParameterName(declarations[1]), "10pt" } } }; return new CssStatement { Selectors = selector.ToArray(), Declarations = new Dictionary<string, string> { {GetParameterName(declarations[0]), "12pt" }, {declarations[1].Parameters.Single().Name.Replace('_', '-'), "10pt" } } };
  29. private static string GetParameterName(Expression<Func<string, string>> declaration) => declaration.Parameters.Single().Name.Replace('_', '-'); private

    static string GetParameterName(Expression<Func<string, string>> declaration) { return declaration.Parameters.Single().Name.Replace('_', '-'); } リファクタ リング
  30. [Test] public void Helperを使ったCssの組み立てでは値を反映します() { var tested = "H2".Css( font_size

    => "10pt", line_height => "12pt"); Expect(tested.ToString(), Is.EqualTo( @"H2 { font-size: 10pt; line-height: 12pt }")); } レッド
  31. グリーン return new CssStatement { Selectors = selector.ToArray(), Declarations =

    new Dictionary<string, string> { {GetParameterName(declarations[0]), declarations[0].Compile().Invoke("") }, {GetParameterName(declarations[1]), declarations[1].Compile().Invoke("") } } }; return new CssStatement { Selectors = selector.ToArray(), Declarations = new Dictionary<string, string> { {GetParameterName(declarations[0]), "12pt" }, {GetParameterName(declarations[1]), "10pt" } } };
  32. return new CssStatement { Selectors = selector.ToArray(), Declarations = new

    Dictionary<string, string> { {GetParameterName(declarations[0]), GetValue(declarations[0]) }, {GetParameterName(declarations[1]), declarations[1].Compile().Invoke("") } } }; return new CssStatement { Selectors = selector.ToArray(), Declarations = new Dictionary<string, string> { {GetParameterName(declarations[0]), declarations[0].Compile().Invoke("") }, {GetParameterName(declarations[1]), declarations[1].Compile().Invoke("") } } }; リファクタ リング
  33. return new CssStatement { Selectors = selector.ToArray(), Declarations = new

    Dictionary<string, string> { {GetParameterName(declarations[0]), GetValue(declarations[0]) }, {GetParameterName(declarations[1]), GetValue(declarations[1]) } } }; return new CssStatement { Selectors = selector.ToArray(), Declarations = new Dictionary<string, string> { {GetParameterName(declarations[0]), GetValue(declarations[0]) }, {GetParameterName(declarations[1]), declarations[1].Compile().Invoke("") } } }; リファクタ リング
  34. return new CssStatement { Selectors = selector.ToArray(), Declarations = new

    Dictionary<string, string> { {GetParameterName(declarations[0]), GetValue(declarations[0]) }, {GetParameterName(declarations[1]), GetValue(declarations[1]) } } }; return new CssStatement { Selectors = selector.ToArray(), Declarations = declarations.ToDictionary( declaration => GetParameterName(declaration), declaration => GetValue(declaration)) }; リファクタ リング
  35. [Test] public void 指定したStatementsがプロパティとして取得できます() { var statements = new[] {

    new CssStatement() }; var tested = new CssFile(@"C:¥File1.css"); tested.Statements = statements; Expect(tested.Statements, Is.SameAs(statements)); } レッド
  36. グリーン public class CssFile { public string Path { get;

    private set; } public CssStatement[] Statements { get; set; } public class CssFile { public string Path { get; private set; }
  37. レッド [SetUp] public void SetUp() { if (File.Exists(@"C:¥File1.css")) { File.Delete(@"C:¥File1.css");

    } } [Test] public void SaveでCssの保存ができます() { var tested = new CssFile(@"C:¥File1.css", new[] { "H1", "H2" }.Css( font_size => "12pt", line_height => "10pt")); tested.Save(); Expect(File.ReadAllText(@"C:¥File1.css"), Is.EqualTo( @"H1, H2 { font-size: 12pt; line-height: 10pt }")); }
  38. レッド public class CssFile { public string Path { get;

    private set; } public CssStatement[] Statements { get; set; } public CssFile(string path) { Path = path; } } public class CssFile { CssStatement cssStatement; public string Path { get; private set; } public CssStatement[] Statements { get; set; } public CssFile(string path) { Path = path; } public CssFile(string path, CssStatement cssStatement) {} public void Save() {} }
  39. グリーン public CssFile(string path, CssStatement cssStatement) : this(path) { this.cssStatement

    = cssStatement; } public void Save() { File.WriteAllText(Path, cssStatement.ToString()); } public CssFile(string path, CssStatement cssStatement) {} public void Save() {}
  40. 考えてはいけないこと レッド • 実装方法 • 実装しやすいかどうか • テストの網羅性 グリーン •

    きちんとしたわかりやすい設計 • アルゴリズムの正当性 • ミスしていないことを注意深く確認する リファクタ リング • 機能追加 • 機能変更 • ミスしていないことを注意深く確認する