[易学易懂系列|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的一种。
它也是遵守如下开发流程:
我们今天要学习的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