devashishdxt / cli-table

Rust crate for printing tables on command line.
Apache License 2.0
120 stars 9 forks source link

Table Output Looks Very Weird In Integration Test? #38

Closed JimLynchCodes closed 4 months ago

JimLynchCodes commented 1 year ago

Hi! I used the same code here to render a table in my terminal that looks pretty nice when I run it with cargo run. 👍

Screen Shot 2023-04-03 at 12 49 24 AM

Now I am trying to write an integration test that expects this output to be printed to the console...

Here is the code that I'm trying:

use assert_cmd::prelude::*;
use std::process::Command;
use std::str;

#[test]
fn renders_the_table() -> Result<(), Box<dyn std::error::Error>> {
    let output_bytes = Command::cargo_bin("table_of_chairs")?
        .output()
        .unwrap()
        .stdout;

    let output_str = match str::from_utf8(&output_bytes) {
        Ok(val) => val,
        Err(_) => panic!("got non UTF-8 data from stdout"),
    };

    assert_eq!(
        output_str,
        "
+------------+----------------+
| Name       | Age (in years) |
+------------+----------------+
| Tom        |             10 |
+------------+----------------+
| Jerry      |             15 |
+------------+----------------+
| Scooby Doo |             20 |
+------------+----------------+
");

    Ok(())
}

For some reason the output looks really bizarre in the test... lots of strange `{1b} things...

test renders_the_table ... FAILED

failures:

---- renders_the_table stdout ----
thread 'renders_the_table' panicked at 'assertion failed: `(left == right)`
  left: `"\u{1b}[0m\u{1b}[1m+\u{1b}[0m\u{1b}[0m\u{1b}[1m------------\u{1b}[0m\u{1b}[0m\u{1b}[1m+\u{1b}[0m\u{1b}[0m\u{1b}[1m----------------\u{1b}[0m\u{1b}[0m\u{1b}[1m+\n\u{1b}[0m\u{1b}[0m\u{1b}[0m\u{1b}[1m|\u{1b}[0m\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[0m\u{1b}[1mName      \u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[1m|\u{1b}[0m\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[0m\u{1b}[1mAge (in years)\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[1m|\u{1b}[0m\u{1b}[0m\u{1b}[1m\n\u{1b}[0m\u{1b}[0m\u{1b}[0m\u{1b}[1m+\u{1b}[0m\u{1b}[0m\u{1b}[1m------------\u{1b}[0m\u{1b}[0m\u{1b}[1m+\u{1b}[0m\u{1b}[0m\u{1b}[1m----------------\u{1b}[0m\u{1b}[0m\u{1b}[1m+\n\u{1b}[0m\u{1b}[0m\u{1b}[0m\u{1b}[1m|\u{1b}[0m\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[0mTom       \u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[1m|\u{1b}[0m\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[0m            10\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[1m|\u{1b}[0m\u{1b}[0m\u{1b}[1m\n\u{1b}[0m\u{1b}[0m\u{1b}[0m\u{1b}[1m+\u{1b}[0m\u{1b}[0m\u{1b}[1m------------\u{1b}[0m\u{1b}[0m\u{1b}[1m+\u{1b}[0m\u{1b}[0m\u{1b}[1m----------------\u{1b}[0m\u{1b}[0m\u{1b}[1m+\n\u{1b}[0m\u{1b}[0m\u{1b}[0m\u{1b}[1m|\u{1b}[0m\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[0mJerry     \u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[1m|\u{1b}[0m\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[0m            15\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[1m|\u{1b}[0m\u{1b}[0m\u{1b}[1m\n\u{1b}[0m\u{1b}[0m\u{1b}[0m\u{1b}[1m+\u{1b}[0m\u{1b}[0m\u{1b}[1m------------\u{1b}[0m\u{1b}[0m\u{1b}[1m+\u{1b}[0m\u{1b}[0m\u{1b}[1m----------------\u{1b}[0m\u{1b}[0m\u{1b}[1m+\n\u{1b}[0m\u{1b}[0m\u{1b}[0m\u{1b}[1m|\u{1b}[0m\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[0mScooby Doo\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[1m|\u{1b}[0m\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[0m            20\u{1b}[0m\u{1b}[1m \u{1b}[0m\u{1b}[0m\u{1b}[1m|\u{1b}[0m\u{1b}[0m\u{1b}[1m\n\u{1b}[0m\u{1b}[0m\u{1b}[0m\u{1b}[1m+\u{1b}[0m\u{1b}[0m\u{1b}[1m------------\u{1b}[0m\u{1b}[0m\u{1b}[1m+\u{1b}[0m\u{1b}[0m\u{1b}[1m----------------\u{1b}[0m\u{1b}[0m\u{1b}[1m+\n\u{1b}[0m\u{1b}[0m"`,
 right: `"\n+------------+----------------+\n| Name       | Age (in years) |\n+------------+----------------+\n| Tom        |             10 |\n+------------+----------------+\n| Jerry      |             15 |\n+------------+----------------+\n| Scooby Doo |             20 |\n+------------+----------------+\n"`', tests/renders_the_table.rs:17:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

failures:
    renders_the_table

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s

Is the table output not utf8? Is there some other way I should be getting the stdout text so that it's in the same format as it looks when it's printed in the console to be read by a human?

Thanks!

devashishdxt commented 1 year ago

Hi. The extra characters are for colouring information. You can set ColorChoice::Never to stop printing coloured output for integration tests. https://docs.rs/cli-table/latest/cli_table/struct.TableStruct.html#method.color_choice

Please let me know if it doesn't work.

JimLynchCodes commented 1 year ago

thanks @devashishdxt! How can I use ColorChoice::Never to actually set the color in my integration test though? By then hasn't the table already been constructed?

JimLynchCodes commented 1 year ago

Hmmm I tried to use the cfg macros to control the color choice, but actually this doesn't even work because for integration tests it should use the #[cfg(not(test))] one... 🤔

let table = vec![
    vec!["Tom".cell(), 10.cell().justify(Justify::Right)],
    vec!["Jerry".cell(), 15.cell().justify(Justify::Right)],
    vec!["Scooby Doo".cell(), 20.cell().justify(Justify::Right)],
]
.table()
.title(vec![
    "Name".cell().bold(true),
    "Age (in years)".cell().bold(true),
])
.color_choice(get_color_choice())     // <--- new thing
.bold(true);

...

#[cfg(not(test))]
fn get_color_choice() -> ColorChoice {
    ColorChoice::Auto
}

#[cfg(test)]
fn get_color_choice() -> ColorChoice {
    ColorChoice::Never
}
devashishdxt commented 1 year ago

You can just use an environment variable when running integration tests and use that environment variable to disable coloured output. Alternatively, you can try to set NO_COLOR environment variable which should ideally not output any colour.

Read more about this here: https://github.com/BurntSushi/termcolor#automatic-color-selection