zoukankan      html  css  js  c++  java
  • [易学易懂系列|rustlang语言|零基础|快速入门|(29)|实战6:BDD工具cucumber_rust]

    [易学易懂系列|rustlang语言|零基础|快速入门|(29)|实战6:BDD工具cucumber_rust]

    项目实战

    实战6:BDD工具cucumber_rust

    今天我们来学习下BDD行为驱动测试工具cucumber_rust。

    关于BDD,可以简单看看这些介绍:

    https://www.cnblogs.com/superhin/p/11454716.html#bdd%E4%BB%8B%E7%BB%8D

    https://www.jianshu.com/p/0389360ac58f

    https://www.infoq.cn/article/2011/02/BDD-ATDD

    简单来说,BDD是一种更好,更直观的一种测试驱动开发方法 。

    它也是TDD的一种。

    它也是遵守如下开发流程:

    img

    我们今天要学习的cucumber_rust,是BDD的rust语言版本:

    好吧,我们现在开始。

    先用命令创建工程:

    cargo new bdd_with_cucumber
    

    然后,我们在文件Cargo.toml加入依赖:

    [[test]]
    name = "cucumber"
    harness = false # Allows Cucumber to print output instead of libtest
    
    [dev-dependencies]
    cucumber = { package = "cucumber_rust", version = "^0.6.0" } 
    

    在当前工程目录下创建目录:tests和features,目录结构如下 :

    bdd_with_cucumber
    ├── Cargo.lock
    ├── Cargo.toml
    ├── tests
    ├── features
    ├── src
    │   └── main.rs
    └── target
        └── debug
            └── ...
    

    我们在tests目录下,创建文件:cucumber.rs,加入如下代码:

    use cucumber::{cucumber, steps, before, after};
    
    pub struct MyWorld {
        // You can use this struct for mutable context in scenarios.
        foo: String
    }
    
    impl cucumber::World for MyWorld {}
    impl std::default::Default for MyWorld {
        fn default() -> MyWorld {
            // This function is called every time a new scenario is started
            MyWorld { 
                foo: "a default string".to_string()
            }
        }
    }
    
    mod example_steps {
        use cucumber::steps;
        
        // Any type that implements cucumber::World + Default can be the world
        steps!(crate::MyWorld => {
            given "I am trying out Cucumber" |world, step| {
                world.foo = "Some string".to_string();
                // Set up your context in given steps
            };
    
            when "I consider what I am doing" |world, step| {
                // Take actions
                let new_string = format!("{}.", &world.foo);
                world.foo = new_string;
            };
    
            then "I am interested in ATDD" |world, step| {
                // Check that the outcomes to be observed have occurred
                assert_eq!(world.foo, "Some string.");
            };
    
            then regex r"^we can (.*) rules with regex$" |world, matches, step| {
                // And access them as an array
                assert_eq!(matches[1], "implement");
            };
    
            then regex r"^we can also match (d+) (.+) types$" (usize, String) |world, num, word, step| {
                // `num` will be of type usize, `word` of type String
                assert_eq!(num, 42);
                assert_eq!(word, "olika");
            };
    
            then "we can use data tables to provide more parameters" |world, step| {
                let table = step.table().unwrap().clone();
    
                assert_eq!(table.header, vec!["key", "value"]);
    
                let expected_keys = table.rows.iter().map(|row| row[0].to_owned()).collect::<Vec<_>>();
                let expected_values = table.rows.iter().map(|row| row[1].to_owned()).collect::<Vec<_>>();
    
                assert_eq!(expected_keys, vec!["a", "b"]);
                assert_eq!(expected_values, vec!["fizz", "buzz"]);
            };
        });
    }
    
    // Declares a before handler function named `a_before_fn`
    before!(a_before_fn => |scenario| {
    
    });
    
    // Declares an after handler function named `an_after_fn`
    after!(an_after_fn => |scenario| {
    
    });
    
    // A setup function to be called before everything else
    fn setup() {
        
    }
    
    cucumber! {
        features: "./features", // Path to our feature files
        world: crate::MyWorld, // The world needs to be the same for steps and the main cucumber call
        steps: &[
            example_steps::steps // the `steps!` macro creates a `steps` function in a module
        ],
        setup: setup, // Optional; called once before everything
        before: &[
            a_before_fn // Optional; called before each scenario
        ], 
        after: &[
            an_after_fn // Optional; called after each scenario
        ] 
    }
    

    然后,我们在目录:features下创建文件:example.feature,加入如下代码:

    Feature: Example feature
    
        Scenario: An example scenario
            Given I am trying out Cucumber
            When I consider what I am doing
            Then I am interested in ATDD
            And we can implement rules with regex
    

    然后,我们运行命令:

    cargo test --test cucumber
    

    运行结果如下:

    
    Feature: Example feature
     \?E:code
    ustProjectdd_with_cucumber_rustfeaturesexample.feature:1:1
    
     Scenario: An example scenario
     \?E:code
    ustProjectdd_with_cucumber_rustfeaturesexample.feature:3:15
      ✔ Given I am trying out Cucumber
     \?E:code
    ustProjectdd_with_cucumber_rustfeaturesexample.feature:4:9
      ✔ When I consider what I am doing
     \?E:code
    ustProjectdd_with_cucumber_rustfeaturesexample.feature:5:9
      ✔ Then I am interested in ATDD
     \?E:code
    ustProjectdd_with_cucumber_rustfeaturesexample.feature:6:9
      ✔ And we can implement rules with regex
     \?E:code
    ustProjectdd_with_cucumber_rustfeaturesexample.feature:7:9
    
    1 features
    1 scenarios (1 passed)
    4 steps (4 passed)
    

    以上,希望对你有用。

    如果遇到什么问题,欢迎加入:rust新手群,在这里我可以提供一些简单的帮助,加微信:360369487,注明:博客园+rust
    

    github地址:https://github.com/gyc567/bdd_with_cucumber_rust/tree/master

    https://blog.testlodge.com/what-is-bdd/

    https://cucumber.io/

    https://www.agilealliance.org/glossary/bdd/

  • 相关阅读:
    rabbitmq 学习10channel 说明
    ASP.NET中进行消息处理(MSMQ) 一
    ThreadLocal原理及用法详解
    设计模式责任链模式
    枚举详解之EnumSet、EnumMap用法
    设计模式策略模式和工厂模式结合使用
    Java并发编程系列之CyclicBarrier详解
    [解题报告]求平均成绩
    [解题报告]1005 Number Sequence
    [解题报告]1013Digital Roots
  • 原文地址:https://www.cnblogs.com/gyc567/p/12121854.html
Copyright © 2011-2022 走看看