How to only Rust for web front_end - test & bench
Published: 2020-08-11 08:00:32


### 4 - Let's try test & benchmark

#### Let's test that thing


Let's add the following in `Cargo.toml`

`Cargo.toml`
```Toml
[dev-dependencies]
wasm-bindgen-test = "0.3"
```

Let's make a test file

`./tests/web.rs`

```Rust

//! Test suite for the Web and headless browsers.

#![cfg(target_arch = "wasm32")]

extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;

extern crate seeded_game_of_life;
use seeded_game_of_life::universe::Universe;
wasm_bindgen_test_configure!(run_in_browser);

#[wasm_bindgen_test]
fn pass() {
    assert_eq!(1 + 1, 2);
}

#[cfg(test)]
pub fn input_spaceship() -> Universe {
    let mut universe = Universe::new();
    universe.set_width(6);
    universe.set_height(6);
    universe.set_cells(&[(1, 2), (2, 3), (3, 1), (3, 2), (3, 3)]);
    universe
}

#[cfg(test)]
pub fn expected_spaceship() -> Universe {
    let mut universe = Universe::new();
    universe.set_width(6);
    universe.set_height(6);
    universe.set_cells(&[(2, 1), (2, 3), (3, 2), (3, 3), (4, 2)]);
    universe
}

#[wasm_bindgen_test]
pub fn test_tick() {
    // Let's create a smaller Universe with a small spaceship to test!
    let mut input_universe = input_spaceship();

    // This is what our spaceship should look like
    // after one tick in our universe.
    let expected_universe = expected_spaceship();

    // Call `tick` and then see if the cells in the `Universe`s are the same.
    input_universe.tick();
    assert_eq!(&input_universe.get_cells(), &expected_universe.get_cells());
}


```

`wasm-pack test --firefox` and then click on the address and you should see the test in firefox

You can do the same if you have Chrome on your computer of course :)

At the moment, since today 29/07/2020 

`wasm-pack test --firefox --headless` seems to fail. I made an issue about it there https://github.com/rustwasm/wasm-bindgen/issues/2261


Anyway testing is easy and we can also make standard tests as well

`tests/universe.rs`
```Rust
#[cfg(test)]
mod tests {
    use seeded_game_of_life::universe::Universe;

    #[test]
    fn big_bang_works() {
       let universe = Universe::new();


        assert_eq!(universe.width(),64);
        assert_eq!(universe.height(),64);
    }
}
```

#### Let's bench it !

`rustup default nightly`

We need the `Darkside` if we want to use some features for benchmarking.

`./benches/bench.rs`
```Rust
#![feature(test)]
extern crate seeded_game_of_life;
extern crate test;

use seeded_game_of_life::universe::Universe;

#[bench]
fn universe_ticks(b: &mut test::Bencher) {
    let mut universe = Universe::new();

    b.iter(|| {
        universe.tick();
    });
}

```

You should have something like this

```
Finished bench [optimized] target(s) in 5.83s
     Running target/release/deps/seeded_game_of_life-e5bb887774c98fd8

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/release/deps/bench-a3412253977e35f0

running 1 test
test universe_ticks ... bench:      38,410 ns/iter (+/- 29,201)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out

```

NB : There are few differences here compare to the [original tutorial](https://rustwasm.github.io/docs/book/game-of-life/time-profiling.html) :
```
We also have to comment out all the #[wasm_bindgen] annotations, and the "cdylib" bits from Cargo.toml or else building native code will fail and have link errors.

```
- No need to care about  `#[wasm_bindgen]`
- No need to remove  `"cdylib"`



Probably because of the `Seed` magic, our rust code does not need the tag, so it is easier :D

Now if we compare to a javascript version of the code base :

- No need to find a library like jest/mocha or other to make test because rust has everything we need :D
- Tags and tools are there to target which kind of test we do
- Benchmark code as native gives us easy overview of performance ( I never had such opportunity in js/ts) , can use `perf` on Linux

To resume, test & benchmark were already easy because of Rust, now it is even more easier since there is only Rust <3 . Thank you Seed !

###5 - How to improve performances

Of course, there are many ways to improve the performances. 

- Take care more of what we are doing in the code:
    - correct type ? 
    - conversion ? 
    - call to DOM ?
    - follow the doc :D
    
- Making a specific build for release:
   - small compiled code strategy
   - faster runtime strategy
   
   

Now in the code we have, we could actually remove every code like `document()` or `canvas()` and use `Ref` and access their state in the `M̀odel`

We can also use options for building as mentioned in the original tutorial. Let's try it!

`Cargo.toml`
```Toml
[profile.release]
lto = true
opt-level = 'z'
codegen-units = 1

[package.metadata.wasm-pack.profile.release]
wasm-opt = ['-O3']

```

You can now run `cargo make build_release`

After refreshing your web browser, you will see that you are at 60 fps always with this size of grid and max ticks.
For me going from 40fps --ish to 60 is a nice improvement :D

You can try to compare the different generated packages if you want with the help of the [tutorial](https://rustwasm.github.io/docs/book/game-of-life/time-profiling.html)


###6 - Conclusion


There is much to say :D and I already talked/wrote sooo much :P

We just have shown together with this post that we can use `Rust` only ( with still html +css of course ) to code **web** `front_end` work.

From a personal point of view, I think of `Rust` as a language like **Latin** or **Icelandic**:

- It can be very short and effective and sometimes very long because of the possibilities to add much context and details that enhance the sens of it.
- Gives more control and nuances on what we need to say, write and communicate.

Rust is **rich** and **powerful** with a `compiler` who moves so many errors and bugs from `run_time` to `compile_time`. 

- It asks us to be better programmers & produce better code
- It secures the code we produce
- It really does indicate/encourage good practice and consistency ( Consistency in Javscript/Typescript even inside the same **dev team** is very hard to accomplish)
- It makes you **love** and **hate** the compiler at the same time **De l'amour à la haine, il n'y a qu'un pas** :D


From a 5 years experience web-programmer that I am :

I really did enjoy my time with React/Redux. Especially redux, because it gives so much control and predictability over pure javascript. Same about Ngrx on Angular.
So I got a good time on React & Angular, but I also know all the pains, the endless maintenance and flood of dependencies to take care of in daily work.
They are part of my experience and I do not have any regret about them. 
But now I have some friends who want to start Web stuff and the layer of complexity in Js/Ts/React/Angular∕vue environment are a huge gap to fight.

All the safety and paradigm ( & soo much more ) made by the front-end frameworks like React or Angular to make web development possible are now more accessible with Rust with much lighter abstraction.


Here are few of the many benefits I see by using **Rust/Seed**

- One language for all logic
- Less dependencies
- Code robust and easy to predict & trust
- We have state_management included
- Visually more organized & structured code
- Higher productivity
- Compiler that helps us to build Robust/Solid Code
- Less time to debug stuff
- Much more predictability
- Easy to maintain
- One language for front_end & back_end
- More control on performances
- Probably better performances in the future also as well


We also have some challenges of course

- IDEs still do not support all the disruptive concepts from Rust
- Seed is not ready for production
- We have still some generated js
- No extension to watch the state at runtime in your web browser like our **lovely** `redux-dev-tools` can do 
- Not sure we can debug the code at runtime neither , but do we need it ?
- No libraries available for specific needs, you will need to do it by yourself ( no UI library for now like Google Material or Bootstrap I think)


Here is the [source](https://github.com/arn-the-long-beard/seeded_game_of_life) code for this post.

Some parts of the code are gonna be updated and improved as I explained. I will do a new branch for that and link it below.

Rust + Seed made me happy to code again. It really make me feel to be part of a great adventure, meet new people, get new skills and discover new opportunities ! There is such much to build :)
 
 
Please guys, **try** & **have fun** & **comment** !!!