Thread overview
Unit testing a function returning void
Nov 03, 2022
Bruno Pagis
Nov 03, 2022
rikki cattermole
Nov 03, 2022
Imperatorn
Nov 03, 2022
Imperatorn
Nov 03, 2022
Paul Backus
Nov 03, 2022
Ali Çehreli
Nov 03, 2022
H. S. Teoh
Nov 03, 2022
Sergey
November 03, 2022

Good morning,
I have the following class:

class A {
  int[] array;

  ...

  void print() {
    writeln("array = ", this.array);
  }
}

I would like to unit test the print function (yes, I know, not very useful on the above example since print is merely a duplicate of writeln...). Is there a way to use assert to test the output of the print function to stdout? Something like:

A myClass= new A;
myClass.array = [1,2];
assert(myClass.print() == "array = [1,2]"); // I know that print does not return anything so this is wrong, but you get the idea :-)

Thanks.

November 03, 2022
You could redirect stdout to a file of your choosing and test against that.

Although ideally you would instead take as an argument to print some sort of output range or Appender. Then you could test against that instead.
November 03, 2022

On Thursday, 3 November 2022 at 10:00:27 UTC, Bruno Pagis wrote:

>

Good morning,
I have the following class:

class A {
  int[] array;

  ...

  void print() {
    writeln("array = ", this.array);
  }
}

I would like to unit test the print function (yes, I know, not very useful on the above example since print is merely a duplicate of writeln...). Is there a way to use assert to test the output of the print function to stdout? Something like:

A myClass= new A;
myClass.array = [1,2];
assert(myClass.print() == "array = [1,2]"); // I know that print does not return anything so this is wrong, but you get the idea :-)

Thanks.

Just so we understand, do you want to verify that the output is indeed directed to stdout and not some other stream?

November 03, 2022

On Thursday, 3 November 2022 at 10:00:27 UTC, Bruno Pagis wrote:

>

Good morning,
I have the following class:

class A {
  int[] array;

  ...

  void print() {
    writeln("array = ", this.array);
  }
}

I would like to unit test the print function (yes, I know, not very useful on the above example since print is merely a duplicate of writeln...). Is there a way to use assert to test the output of the print function to stdout?

The easiest way to do this is to modify the function so it can output somewhere other than stdout. Then you can have it output to a file in the unittest, and check the contents of the file to verify the result.

For example:

import std.stdio;

class A
{
    int[] a;

    this(int[] a) { this.a = a; }

    void print(File output = stdout) {
        output.writeln("array = ", this.a);
    }
}

unittest {
    import std.file;

    A a = new A([1, 2]);
    a.print(File("test.txt", "wb"));
    assert(readText("test.txt") == "array = [1, 2]\n");
}
November 03, 2022
On 11/3/22 03:00, Bruno Pagis wrote:

>    void print() {
>      writeln("array = ", this.array);
>    }

Similar to Paul Backus's program but I would try to avoid the file system for unit tests when possible. In this case, you can print into a sink, which can be useful in other ways as well:

import std.stdio;

class A
{
    int[] a;

    this(int[] a) { this.a = a; }

    void toString(scope void delegate(in char[]) sink) const {
        import std.conv : text;
        sink("array = ");
        sink(this.a.text); // or this.a.to!string

        // The following alternative may be a little heavier weight:
        // import std.format : formattedWrite;
        // sink.formattedWrite!"array = %s"(this.a);
    }

    void print() {
        writeln(this);
    }
}

unittest {
    import std.file;

    A a = new A([1, 2]);

    import std.conv : text;
    assert(a.text == "array = [1, 2]");
}

void main() {}

toString is the textual representation of the object. If you don't want the same output for that purpose, you can use a different name from toString but you have to use an explicit "sink" but I really think the above is what you want. :)

Ali

November 03, 2022
On Thu, Nov 03, 2022 at 08:51:52AM -0700, Ali Çehreli via Digitalmars-d-learn wrote:
> On 11/3/22 03:00, Bruno Pagis wrote:
> 
> >    void print() {
> >      writeln("array = ", this.array);
> >    }
> 
> Similar to Paul Backus's program but I would try to avoid the file system for unit tests when possible. In this case, you can print into a sink, which can be useful in other ways as well:
[...]

Alternatively, you can templatize on File to make it swappable with a mock object:

	void myfunc(File = std.stdio.File)(File output = stdout) {
		output.writeln(...);
	}

	unittest {
		struct MockFile {
			string output;
			void writeln(Args...)(Args args) {
				output ~= format(args);
			}
		}
		MockFile mock;
		myfunc(mock);
		assert(mock.output == ...);
	}


T

-- 
"Maybe" is a strange word.  When mom or dad says it it means "yes", but when my big brothers say it it means "no"! -- PJ jr.
November 03, 2022

On Thursday, 3 November 2022 at 10:00:27 UTC, Bruno Pagis wrote:

>

Good morning,

I would like to unit test the print function (yes, I know, not very useful on the above example since print is merely a duplicate of writeln...). Is there a way to use assert to test the output of the print function to stdout? Something like:

Just for curiosity: we have this tremendous list of testing libraries https://code.dlang.org/search?q=test

Maybe one of them has the 'capture stdout' (https://docs.pytest.org/en/7.1.x/how-to/capture-stdout-stderr.html) feature?

November 03, 2022

On Thursday, 3 November 2022 at 10:26:04 UTC, Imperatorn wrote:

>

On Thursday, 3 November 2022 at 10:00:27 UTC, Bruno Pagis wrote:

>

Good morning,
I have the following class:

class A {
  int[] array;

  ...

  void print() {
    writeln("array = ", this.array);
  }
}

I would like to unit test the print function (yes, I know, not very useful on the above example since print is merely a duplicate of writeln...). Is there a way to use assert to test the output of the print function to stdout? Something like:

A myClass= new A;
myClass.array = [1,2];
assert(myClass.print() == "array = [1,2]"); // I know that print does not return anything so this is wrong, but you get the idea :-)

Thanks.

Just so we understand, do you want to verify that the output is indeed directed to stdout and not some other stream?

Just for documentation purposes, if you wished to redirect I believe you could do something like this (untested):

auto original = stdout; // save
stdout.open(newdest, "wt"); // redirect

// do stuff, check newdest

stdout = original; // restore