[易学易懂系列|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的一种。

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

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

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

好吧,我们现在开始。

先用命令创建工程:


1
2
1cargo new bdd_with_cucumber
2

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


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

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


1
2
3
4
5
6
7
8
9
10
11
1bdd_with_cucumber
2├── Cargo.lock
3├── Cargo.toml
4├── tests
5├── features
6├── src
7│   └── main.rs
8└── target
9    └── debug
10        └── ...
11

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
1use cucumber::{cucumber, steps, before, after};
2
3pub struct MyWorld {
4    // You can use this struct for mutable context in scenarios.
5    foo: String
6}
7
8impl cucumber::World for MyWorld {}
9impl std::default::Default for MyWorld {
10    fn default() -> MyWorld {
11        // This function is called every time a new scenario is started
12        MyWorld {
13            foo: "a default string".to_string()
14        }
15    }
16}
17
18mod example_steps {
19    use cucumber::steps;
20    
21    // Any type that implements cucumber::World + Default can be the world
22    steps!(crate::MyWorld => {
23        given "I am trying out Cucumber" |world, step| {
24            world.foo = "Some string".to_string();
25            // Set up your context in given steps
26        };
27
28        when "I consider what I am doing" |world, step| {
29            // Take actions
30            let new_string = format!("{}.", &world.foo);
31            world.foo = new_string;
32        };
33
34        then "I am interested in ATDD" |world, step| {
35            // Check that the outcomes to be observed have occurred
36            assert_eq!(world.foo, "Some string.");
37        };
38
39        then regex r"^we can (.*) rules with regex$" |world, matches, step| {
40            // And access them as an array
41            assert_eq!(matches[1], "implement");
42        };
43
44        then regex r"^we can also match (\d+) (.+) types$" (usize, String) |world, num, word, step| {
45            // `num` will be of type usize, `word` of type String
46            assert_eq!(num, 42);
47            assert_eq!(word, "olika");
48        };
49
50        then "we can use data tables to provide more parameters" |world, step| {
51            let table = step.table().unwrap().clone();
52
53            assert_eq!(table.header, vec!["key", "value"]);
54
55            let expected_keys = table.rows.iter().map(|row| row[0].to_owned()).collect::<Vec<_>>();
56            let expected_values = table.rows.iter().map(|row| row[1].to_owned()).collect::<Vec<_>>();
57
58            assert_eq!(expected_keys, vec!["a", "b"]);
59            assert_eq!(expected_values, vec!["fizz", "buzz"]);
60        };
61    });
62}
63
64// Declares a before handler function named `a_before_fn`
65before!(a_before_fn => |scenario| {
66
67});
68
69// Declares an after handler function named `an_after_fn`
70after!(an_after_fn => |scenario| {
71
72});
73
74// A setup function to be called before everything else
75fn setup() {
76    
77}
78
79cucumber! {
80    features: "./features", // Path to our feature files
81    world: crate::MyWorld, // The world needs to be the same for steps and the main cucumber call
82    steps: &[
83        example_steps::steps // the `steps!` macro creates a `steps` function in a module
84    ],
85    setup: setup, // Optional; called once before everything
86    before: &[
87        a_before_fn // Optional; called before each scenario
88    ],
89    after: &[
90        an_after_fn // Optional; called after each scenario
91    ]
92}
93

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


1
2
3
4
5
6
7
8
1Feature: Example feature
2
3    Scenario: An example scenario
4        Given I am trying out Cucumber
5        When I consider what I am doing
6        Then I am interested in ATDD
7        And we can implement rules with regex
8

然后,我们运行命令:


1
2
1cargo test --test cucumber
2

运行结果如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1
2Feature: Example feature
3 \\?\E:\code\rustProject\bdd_with_cucumber_rust\features\example.feature:1:1
4
5 Scenario: An example scenario
6 \\?\E:\code\rustProject\bdd_with_cucumber_rust\features\example.feature:3:15
7  ✔ Given I am trying out Cucumber
8 \\?\E:\code\rustProject\bdd_with_cucumber_rust\features\example.feature:4:9
9  ✔ When I consider what I am doing
10 \\?\E:\code\rustProject\bdd_with_cucumber_rust\features\example.feature:5:9
11  ✔ Then I am interested in ATDD
12 \\?\E:\code\rustProject\bdd_with_cucumber_rust\features\example.feature:6:9
13  ✔ And we can implement rules with regex
14 \\?\E:\code\rustProject\bdd_with_cucumber_rust\features\example.feature:7:9
15
161 features
171 scenarios (1 passed)
184 steps (4 passed)
19

以上,希望对你有用。


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

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/

给TA打赏
共{{data.count}}人
人已打赏
安全技术

c++ list, vector, map, set 区别与用法比较

2022-1-11 12:36:11

安全运维

MySql在建立索引优化时需要注意的问题

2021-12-11 11:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索