<p>可以使用另一个属性来反转测试中的失败:<code>should_panic</code>。这在测试调用特定的函数会产生错误的函数时很有帮助。例如,让我们测试第八章中的一些我们知道会 panic 的代码:尝试使用 range 语法和并不组成完整字母的字节索引来创建一个字符串 slice。在有<code>#[test]</code>属性的函数之前增加<code>#[should_panic]</code>属性,如列表 11-1 所示:</p>
<pre><codeclass="language-rust">struct Guess {
<figure>
value: u32,
<spanclass="filename">Filename: src/lib.rs</span>
}
<pre><codeclass="language-rust">#[test]
#[should_panic]
impl Guess {
fn slice_not_on_char_boundaries() {
pub fn new(value: u32) -> Guess {
let s = "Здравствуйте";
if value < 1 {
&s[0..1];
panic!("Guess value must be greater than or equal to 1, got {}.",
value);
} else if value > 100 {
panic!("Guess value must be less than or equal to 100, got {}.",
value);
}
Guess {
value: value,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic(expected = "Guess value must be less than or equal to 100")]
fn greater_than_100() {
Guess::new(200);
}
}
}
</code></pre>
</code></pre>
<figcaption>
<p><spanclass="caption">Listing 11-9: Testing that a condition will cause a
<p>Listing 11-1: A test expecting a <code>panic!</code></p>
<code>panic!</code> with a particular panic message </span></p>
</figcaption>
<p>这个测试会通过,因为<code>should_panic</code>属性中<code>expected</code>参数提供的值是<code>Guess::new</code>函数 panic 信息的子字符串。我们可以指定期望的整个 panic 信息,在这个例子中是<code>Guess value must be less than or equal to 100, got 200.</code>。这依赖于 panic 有多独特或动态和你希望测试有多准确。在这个例子中,错误信息的子字符串足以确保函数在<code>else if value > 100</code>的情况下运行。</p>
</figure>
<p>为了观察带有<code>expected</code>信息的<code>should_panic</code>测试失败时会发生什么,让我们再次引入一个 bug 来将<code>if value < 1</code>和<code>else if value > 100</code>的代码块对换:</p>
<p>错误信息表明测试确实如期望 panic 了,不过 panic 信息<code>did not include expected string 'Guess value must be less than or equal to 100'</code>。可以看到我们的到的 panic 信息,在这个例子中是<code>Guess value must be greater than or equal to 1, got 200.</code>。这样就可以开始寻找 bug 在哪了!</p>
<p>可以使用另一个属性来反转测试中的失败:<code>should_panic</code>。这在测试调用特定的函数会产生错误的函数时很有帮助。例如,让我们测试第八章中的一些我们知道会 panic 的代码:尝试使用 range 语法和并不组成完整字母的字节索引来创建一个字符串 slice。在有<code>#[test]</code>属性的函数之前增加<code>#[should_panic]</code>属性,如列表 11-1 所示:</p>
<pre><codeclass="language-rust">struct Guess {
<figure>
value: u32,
<spanclass="filename">Filename: src/lib.rs</span>
}
<pre><codeclass="language-rust">#[test]
#[should_panic]
impl Guess {
fn slice_not_on_char_boundaries() {
pub fn new(value: u32) -> Guess {
let s = "Здравствуйте";
if value < 1 {
&s[0..1];
panic!("Guess value must be greater than or equal to 1, got {}.",
value);
} else if value > 100 {
panic!("Guess value must be less than or equal to 100, got {}.",
value);
}
Guess {
value: value,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic(expected = "Guess value must be less than or equal to 100")]
fn greater_than_100() {
Guess::new(200);
}
}
}
</code></pre>
</code></pre>
<figcaption>
<p><spanclass="caption">Listing 11-9: Testing that a condition will cause a
<p>Listing 11-1: A test expecting a <code>panic!</code></p>
<code>panic!</code> with a particular panic message </span></p>
</figcaption>
<p>这个测试会通过,因为<code>should_panic</code>属性中<code>expected</code>参数提供的值是<code>Guess::new</code>函数 panic 信息的子字符串。我们可以指定期望的整个 panic 信息,在这个例子中是<code>Guess value must be less than or equal to 100, got 200.</code>。这依赖于 panic 有多独特或动态和你希望测试有多准确。在这个例子中,错误信息的子字符串足以确保函数在<code>else if value > 100</code>的情况下运行。</p>
</figure>
<p>为了观察带有<code>expected</code>信息的<code>should_panic</code>测试失败时会发生什么,让我们再次引入一个 bug 来将<code>if value < 1</code>和<code>else if value > 100</code>的代码块对换:</p>
<p>错误信息表明测试确实如期望 panic 了,不过 panic 信息<code>did not include expected string 'Guess value must be less than or equal to 100'</code>。可以看到我们的到的 panic 信息,在这个例子中是<code>Guess value must be greater than or equal to 1, got 200.</code>。这样就可以开始寻找 bug 在哪了!</p>
<spanclass="caption">Listing 11-9: Testing that a condition will cause a
`panic!` with a particular panic message </span>
<figure>
这个测试会通过,因为`should_panic`属性中`expected`参数提供的值是`Guess::new`函数 panic 信息的子字符串。我们可以指定期望的整个 panic 信息,在这个例子中是`Guess value must be less than or equal to 100, got 200.`。这依赖于 panic 有多独特或动态和你希望测试有多准确。在这个例子中,错误信息的子字符串足以确保函数在`else if value > 100`的情况下运行。
<spanclass="filename">Filename: src/lib.rs</span>
```rust
为了观察带有`expected`信息的`should_panic`测试失败时会发生什么,让我们再次引入一个 bug 来将`if value <1`和`elseifvalue> 100`的代码块对换:
#[test]
#[should_panic(expected = "do not lie on character boundary")]
```rust,ignore
fn slice_not_on_char_boundaries() {
if value <1{
let s = "Здравствуйте";
panic!("Guess value must be less than or equal to 100, got {}.", value);
&s[0..1];
} else if value > 100 {
panic!("Guess value must be greater than or equal to 1, got {}.", value);
}
}
```
```
<!-- I will add ghosting in libreoffice /Carol -->
这一次运行`should_panic`测试,它会失败:
<figcaption>
```
running 1 test
test tests::greater_than_100 ... FAILED
failures:
---- tests::greater_than_100 stdout ----
thread 'tests::greater_than_100' panicked at 'Guess value must be greater
than or equal to 1, got 200.', src/lib.rs:10
note: Run with `RUST_BACKTRACE=1` for a backtrace.
note: Panic did not include expected string 'Guess value must be less than or
equal to 100'
Listing 11-2: A test expecting a `panic!` with a particular message
错误信息表明测试确实如期望 panic 了,不过 panic 信息`did not include expected string 'Guess value must be less than or equal to 100'`。可以看到我们的到的 panic 信息,在这个例子中是`Guess value must be greater than or equal to 1, got 200.`。这样就可以开始寻找 bug 在哪了!