Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
richelbilderbeek committed Jul 11, 2024
2 parents 3fbd1cc + bfd04ff commit 3588e71
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 34 deletions.
71 changes: 37 additions & 34 deletions hello_world.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,63 @@
# Hello world

This chapter is a minimal Bevy program.
This chapter is about creating a minimal Bevy program that is completely tested.

The minimal program will create a Bevy `App`
and then run it ([main.rs](https://github.com/richelbilderbeek/bevy_tdd_book_hello_world/blob/master/src/main.rs)):
## First test

```rust
use crate::app::create_app;
mod app;
Our first test is about creating a Bevy program.
The Bevy class for this, is called [`App`](https://docs.rs/bevy/latest/bevy/app/struct.App.html).
Hence, we call the function to create a Bevy program `create_app`.

fn main() {
let mut app = create_app();
app.run();
Our first trivial test will be if `create_app` does something,

Check failure on line 11 in hello_world.md

View workflow job for this annotation

GitHub Actions / check_markdown

Trailing spaces [Expected: 0 or 2; Actual: 1]
i.e. it does not crash:

```rust
fn test_can_create_app() {
create_app();
}
```

The `main` function will not be used in automated testing,
as it starts our game: starting the game
will require that a user needs to do something to close it.
Hence, the `main` function 'just' runs the `App`.
This test will break the code, as the function `create_app` does not exist yet.

The testing takes place in the `create_app` function.
The first two lines of `main.rs` allow us to call the `create_app`
function in the file [app.rs](https://github.com/richelbilderbeek/bevy_tdd_book_hello_world/blob/master/src/app.rs).
## First fix

Our first trivial test will be if `create_app` does something,
i.e. it does not crash:
Here is a possible implementation of `create_app`:

```rust
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_can_create_app() {
create_app();
}
pub fn create_app() -> App {
App::new()
}
```

Writing this test will break the code, as the function `create_app`
does not exist yet.
Another option is to use `return App::new();` in the function body instead.
This, however, does not follow the Rust style recommended by the `clippy`
crate.

Here is the `create_app` function definition that fixes all tests:
## `main.rs`

```rust
use bevy::prelude::*;
The `main` function will not be used in automated testing,
as it starts our game: starting the game
will require that a user needs to do something to close it.
Hence, the `main` function 'just' runs the `App`.

pub fn create_app() -> App {
return App::new();
```rust
fn main() {
let mut app = create_app();
app.add_plugins(DefaultPlugins);
app.run();
}
```

The `main` function does add the Bevy default plugins.

Check failure on line 51 in hello_world.md

View workflow job for this annotation

GitHub Actions / check_markdown

Trailing spaces [Expected: 0 or 2; Actual: 1]
These plugins will add functionality to an `App`, such
as creating a window.
Due to this, our `App` that does nothing can be displayed:

[An empty Bevy App](hello_world.md)

## Conclusion

We can now create an `App`. It does nothing and displays nothing.
We can now create an `App`. It does nothing.
However, we do have tested everything (i.e. nothing) it does!

Full code can be found at [https://github.com/richelbilderbeek/bevy_tdd_book_hello_world](https://github.com/richelbilderbeek/bevy_tdd_book_hello_world)
30 changes: 30 additions & 0 deletions scripts/clone_all_chapters.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash
#
# Clone all chapters in folders next to this one.
#
# This means that after this script, you'll have a folder structure like:
#
# ../bevy_tdd_book
# ../bevy_tdd_book_hello_world
# ../bevy_tdd_book_[other chapters]
#
# Usage:
#
# ./scripts/clone_all_chapters.sh

if [[ "$PWD" =~ scripts$ ]]; then
echo "FATAL ERROR."
echo "Please run the script from the project root. "
echo "Present working director: $PWD"
echo " "
echo "Tip: like this"
echo " "
echo " ./scripts/clone_all_chapters.sh"
echo " "
exit 42
fi

# ls *.md | grep -v [A-Z] | grep -v "faq\\.md"
rscript scripts/clone_all_chapters_impl.R


27 changes: 27 additions & 0 deletions scripts/clone_all_chapters_impl.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Current working directory must end with bevy_tdd_book

pwd <- getwd()

if (!stringr::str_detect(pwd, "bevy_tdd_book$")) {
stop("Run this script in the 'bevy_tdd_book' folder")
}


all_md_files <- list.files(pattern = "md")
md_files <- stringr::str_subset(all_md_files, "[A-Z]", negate = TRUE)
md_files <- stringr::str_subset(md_files, "faq.md", negate = TRUE)
md_files <- stringr::str_subset(md_files, "functions.md", negate = TRUE)
md_files

chapter_names <- stringr::str_sub(md_files, end = -4)

setwd("..")
pwd <- getwd()

testthat::expect_false(stringr::str_detect(pwd, "bevy_tdd_book"))

args <- paste0("clone https://github.com/richelbilderbeek/bevy_tdd_book_", chapter_names)

for (arg in args) {
system2(command = "git", args = arg)
}

0 comments on commit 3588e71

Please sign in to comment.