macro "describe!" is not defined! #48

Closed
xetra11 opened this Issue Mar 7, 2016 · 23 comments

Projects

None yet

3 participants

@xetra11
xetra11 commented Mar 7, 2016

Hey there,

Sorry for this maybe pretty trivial question but I'm new to Rust and want to start my first project with TDD and therefore your crate right away.

I have Multirust and rust nightly 1.9.0
and your stainless 1.4.0

Its compiling fine but running a test (which I tested before using stainless - worked fine) will fail due the undefined macro "describe!". Racer also tells me its not defined on the run.

Can sb. please give me a hint what I'm missing here?

greets
Charlie

@ujh
Collaborator
ujh commented Mar 7, 2016

Stainless is a compiler plugin so you need to enable it. Did you add the two lines that every file in the tests/ folder starts with? Sorry, I'm currently on a phone so I can't copy & paste them here.

@xetra11
xetra11 commented Mar 7, 2016

I added those two lines

add #![feature(plugin)] to the crates attributes - is what the compiler still wants...I did but nothing changed? Still missing something?

@ujh
Collaborator
ujh commented Mar 7, 2016

I have the following in my project:

#![feature(plugin)]
#![cfg_attr(test, plugin(stainless))]

https://github.com/ujh/iomrascalai/blob/master/src/main.rs#L24

@xetra11
xetra11 commented Mar 7, 2016

Hm I really have difficulties with this configuration.
Am I allowed to post my Unit and Test File here so you might have a look what's going the wrong way?

@ujh
Collaborator
ujh commented Mar 7, 2016

Sure!

@xetra11
xetra11 commented Mar 7, 2016

tests.rs

#![feature(plugin,const_fn)]
#![plugin(stainless)]

describe! CanvasRenderer
{
    before_each{
        let mut Canvas = Canvas{
            width: 10,
            height: 10,
            array: vec!['x';10*10],
        };
    }

    it "should fill given char at given coords"{

        let mut renderer: CanvasRenderer = CanvasRenderer::new(&mut canvas);
        renderer.render_point('x', 3,3);
        assert_eq!('x', canvas.array[3*3]);

    }
}

renderay_core.rs

#![feature(plugin)]
#![cfg_attr(tests, plugin(stainless))]

struct Canvas{
    width: usize,
    height: usize,
    array: Vec<char>
}

struct CanvasRenderer<'a>{
    canvas: &'a mut Canvas
}

impl <'a>CanvasRenderer<'a>{
    fn new(canvas: &'a mut Canvas) -> CanvasRenderer{
        CanvasRenderer{
            canvas: canvas
        }
    }

    fn fill(&mut self, fill_symbol: char){
        let canvas = &mut self.canvas;
        let height = canvas.height;
        let width = canvas.width;
        let array: &mut Vec<char> = &mut canvas.array;

        for it_y in 0..height{
            for it_x in 0..width{
                array[(it_x + it_y*width) as usize] = fill_symbol;
            }
        }
    }

    fn render_point(&mut self, fill_symbol: char, pos_x: usize, pos_y: usize){
        let canvas = &mut self.canvas;
        let mut array_to_fill = &mut canvas.array;
        let max_width: usize = canvas.width;
        let max_height: usize = canvas.height;
        let pos_to_draw = pos_x * pos_y;

        if pos_x < 0 || pos_y < 0 {panic!("Not allowed coordinates")};
        if pos_x > max_width || pos_y > max_height {panic!("Coordinates are out of array bounds")};

        array_to_fill[pos_to_draw] = fill_symbol;

    }
}

@ujh
Collaborator
ujh commented Mar 7, 2016

I haven't tried compiling this so I may be wrong. But here are my observations:

  • Is this the whole program? How do you compile those two files together?
  • The plugin and feature declarations are on crate level, i.e. they are only necessary once per program. Just put them in the file that you give to rustc.
  • Internally stainless creates a mod out of the describe! block so you will have to use pub use in your test module so that the ste it is available.
@xetra11
xetra11 commented Mar 8, 2016

Hm no nothing - just can't get it to work with the above code...

@ujh
Collaborator
ujh commented Mar 8, 2016

Hm, maybe this is the wrong place anyway. How about we switch to forum.rustplatz.de?

@utkarshkukreti
Contributor

@xetra11 you have a typo in renderay_core.rs:

#![cfg_attr(tests, plugin(stainless))]

should be

#![cfg_attr(test, plugin(stainless))]
@xetra11
xetra11 commented Mar 8, 2016

I thought test would reference to my tests.rs file?

What does test reference to?

@ujh

Sorry to spam your issues - but mybe it'll help future users ? I hope so :)

@ujh
Collaborator
ujh commented Mar 8, 2016

No, file names only name modules. What you want is the plugin(stainless) definition (?) for the cargo test target but not for the normal code.

@ujh
Collaborator
ujh commented Mar 8, 2016

BTW, that also means that you need to compile and run the tests via Cargo. But doing anything else is wasted effort in Rust anyway.

@ujh
Collaborator
ujh commented Mar 8, 2016

AND those two lines from my program are useful only when you compile the tests together with your code base. Not when you build a library and use it as an external crate. Then you should use the configuration from the tests/ folder in this repo here.

@xetra11
xetra11 commented Mar 8, 2016

Sorry I have to spam this but I really really want this to work (I love TDD)

I have in my src/ folder test.rs and renderay_core.rs

test.rs

#![cfg_attr(plugin, const_fn)]
#![plugin(stainless)]


#![cfg(test)]

mod test{

       pub use super::CanvasRenderer;
        pub use super::Canvas;

    describe! test
    {

        before_each{
            let mut Canvas = Canvas{
                width: 10,
                height: 10,
                array: vec!['x';10*10],
            };
        }

        it "should fill given char at given coords"{

            let mut renderer: CanvasRenderer = CanvasRenderer::new(&mut canvas);
            renderer.render_point('x', 3,3);
            assert_eq!('x', canvas.array[3*3]);

        }
    }
}

renderay_core.rs

struct Canvas{
    width: usize,
    height: usize,
    array: Vec<char>
}

struct CanvasRenderer<'a>{
    canvas: &'a mut Canvas
}

impl <'a>CanvasRenderer<'a>{
    fn new(canvas: &'a mut Canvas) -> CanvasRenderer{
        CanvasRenderer{
            canvas: canvas
        }
    }

    fn fill(&mut self, fill_symbol: char){
        let canvas = &mut self.canvas;
        let height = canvas.height;
        let width = canvas.width;
        let array: &mut Vec<char> = &mut canvas.array;

        for it_y in 0..height{
            for it_x in 0..width{
                array[(it_x + it_y*width) as usize] = fill_symbol;
            }
        }
    }

    fn render_point(&mut self, fill_symbol: char, pos_x: usize, pos_y: usize){
        let canvas = &mut self.canvas;
        let mut array_to_fill = &mut canvas.array;
        let max_width: usize = canvas.width;
        let max_height: usize = canvas.height;
        let pos_to_draw = pos_x * pos_y;

        if pos_x < 0 || pos_y < 0 {panic!("Not allowed coordinates")};
        if pos_x > max_width || pos_y > max_height {panic!("Coordinates are out of array bounds")};

        array_to_fill[pos_to_draw] = fill_symbol;

    }
}

What is the way to get this to work with those two files and the folder structure of .../src/test.rs & .../src/rendera_core.rs

Thanks for you help guys I really apprectiate your time!

Charlie

@ujh
Collaborator
ujh commented Mar 8, 2016

No worries. :)

  • How does your Cargo.toml file look like?
  • In this way you can't even compile them together as there's no main file that somehow references the other file (e.g. via mod tests;).
  • As I said before you can have those plugin, etc. configurations only once per crate. They need to go into the main file you hand to rustc
@ujh
Collaborator
ujh commented Mar 8, 2016

BTW, has the error message changed in the meantime?

@xetra11
xetra11 commented Mar 9, 2016

Cargo.toml

[package]
name = "renderay_rs"
version = "0.0.1"
authors = ["xetra11 <falke_88@hotmail.com>"]

[lib]
path="src/renderay_core.rs"

[dependencies]
stainless = { git = "https://github.com/reem/stainless.git" }

In the test.rs I get an error for this line #![plugin(stainless)] (add [features(plugin)] to the crates attributes to enable)

the example with compiling them together you wrote ("mod tests;") what does tests refer to? The filename of tests.rs (ergo "tests") or the signature of "mod tests {}" which is wrapping around my test code? And where do I need to declare "mod tests;" to make it work?

As I said before you can have those plugin, etc. configurations only once per crate. They need to go into the main file you hand to rustc
Since I start my compiling and testing with cargo I don't hand anything over to rustc so what is the main file in there :/

Charlie

@ujh
Collaborator
ujh commented Mar 9, 2016

OK ... There's a lot to explain here. Can I steal your code (with attribution of course) and write a blog post explaining it all? It may take me a day or two but I think that would be more useful.

@ujh
Collaborator
ujh commented Mar 9, 2016
@xetra11
xetra11 commented Mar 9, 2016

Sure you can! Thanks for your time! I'll gonna share that blog post for sure!

@xetra11
xetra11 commented Mar 9, 2016

great blog now everything works! Thank you!

@xetra11 xetra11 closed this Mar 9, 2016
@ujh
Collaborator
ujh commented Mar 9, 2016

You're welcome. Now I understand this even better and I have new content for my blog. Everyone wins. 😁👌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment