1

I want to write a [DataTestMethod] that uses many [DataRow]s, all containing two byte arrays. But, my problem is that the test method only uses the Data from the last row.

I have written a Test with data rows that just contains integers which works fine. And another one that containes one Byte array and some bools. But I can't get a multiple data rows with two byte arrays to work.

Working Tests:

    [DataTestMethod]
    [DataRow(1, 1, 2)]
    [DataRow(2, 2, 4)]
    [DataRow(3, 3, 6)]
    public void AddTests(int x, int y, int expected)
    {
        Assert.AreEqual(expected, x + y);
    }

    [DataRow(new byte[] { 0x00 }, false, false, false)]
    [DataRow(new byte[] { 0x00 }, true, true, false)]
    [DataRow(new byte[] { 0x00 }, false, true, false)]
    [DataRow(new byte[] { 0x00 }, true, false, false)]
    [DataTestMethod()]
    public void ByteArrayIntegerTest(byte[] key,bool ctorsign, bool tasign,bool expectfail)
    {
        var bi = new ByteArrayInteger(key, ctorsign);
        var result = bi.ToByteArray(tasign);
        if (expectfail)
        {
            CollectionAssert.AreNotEqual(key, result);
        }
        else
        {
            CollectionAssert.AreEqual(key, result);
        }
    }

Not working Test:

    [DataTestMethod]
    [DataRow(new byte[] { 0xCA, 0xFE }, new byte[] { 0xCA, 0xFE })]
    [DataRow(new byte[] { 0x00, 0xCA, 0xFE }, new byte[] { 0xCA, 0xFE })]
    [DataRow(new byte[] { 0x00, 0x00, 0xCA, 0xFE }, new byte[] { 0xCA, 0xFE })]

    public void MinimizeSerialnumberTest(byte[] serialnumber, byte[] expected)
    {
        CollectionAssert.AreEqual(expected, Util.MinimizeSerialnumber(serialnumber));
    }

With the non working test it only ever uses the last provided DataRow. There are no errors and the test runs just fine.

Does Microsoft.VisualStudio.TestTools.UnitTesting not support multiple byte arrays? Or what could be the problem?

Edit: After some more research. Could the Problem be, that DataRowAttribute takes Object, Object[] as parameters in it's constructor? Source

If so, how would I work with that?

2
  • In the test explorer, does it show the test was run 3 times, with the inputs used for each test? Or does it show the test was only run once Commented Aug 30, 2022 at 11:09
  • For the non-working test it shows it only once. For the other two working tests it shows all the test results. Commented Aug 30, 2022 at 11:12

2 Answers 2

2

Edit: After some more research. Could the Problem be, that DataRowAttribute takes Object, Object[] as parameters in it's constructor?

Yes, that seems to be the case. The second parameter is params, so the compiler performs the following translations:

           first argument --+    +--- array of remaining arguments
                            |    |
                            v    v
DataRow(1, 2, 3) -> DataRow(1, new object[] { 2, 3 });
DataRow(1, 2)    -> DataRow(1, new object[] { 2 });

However, the compiler won't translate DataRow(1, someObjectArray) to DataRow(1, new object[] { someObjectArray }), but rather keep the object array as it is. This is necessary in case you want to actually pass an object array containing all (remaining) parameters for your test method.

Since byte[] is implicitly convertible to object[] (an unfortunate legacy left-over from the old days when we didn't have generics), it appears that

  • your byte[] is implicitly converted to an object[] and then
  • this object[] is used as the second parameter,

resulting in the following data row for your test: { 0xCA, 0xFE }, 0xCA, 0xFE (rather than the indented { 0xCA, 0xFE }, { 0xCA, 0xFE }).

If so, how would I work with that?

Explicitly wrap your second parameter in an object[]:

[DataRow(new byte[] { 0xCA, 0xFE }, new object[] { new byte[] { 0xCA, 0xFE } })]
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the good explanation. However, even if I explicitly wrap my parameter, it still only uses the last DataRow I provide. If I use the code I provided in my answer it uses all the DataRows. And right now I can't understand why.
0

I think the problem was the constructor of DataRowAttribute. I changed my data rows to the following and now everything works as intended.

[DataRow(1, new byte[] { 0xCA, 0xFE }, new byte[] { 0xCA, 0xFE })]
[DataRow(2, new byte[] { 0x00, 0xCA, 0xFE }, new byte[] { 0xCA, 0xFE })]

2 Comments

Strange. Did you also add a (dummy) int parameter to your test?
Do you mean the test method? Yes it's now like this: MinimizeSerialnumberTests(int testno, byte[] serialnumber, byte[] expected)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.