bitbonk
bitbonk

Reputation: 49649

Is this a clean BDD/MSpec test?

I have a static class Cryptographic that can Encypt and Decrypt a string. I have written the following specs for this:

[Subject(typeof(Cryptographic))]
class When_encrypting_and_decrypting_a_string
{
    Establish context = () => { input = "teststring"; };

    Because of = () =>
    {
        output = Cryptographic.Decrypt(Cryptographic.Encrypt(input));
    };

    It should_decrypt_what_was_encrypted = () => input.ShouldEqual(output);

    static string input;
    static string output;
}

[Subject(typeof(Cryptographic))]
class When_encrypting_and_decrypting_an_empty_string
{
    Establish context = () => { input = string.Empty; };

    Because of = () =>
    {
        output = Cryptographic.Decrypt(Cryptographic.Encrypt(input));
    };

    It should_decrypt_what_was_encrypted = () => input.ShouldEqual(output);

    static string input;
    static string output;
}

[Subject(typeof(Cryptographic))]
class When_encrypting_and_decrypting_a_null_string
{
    Establish context = () => { input = null; };

    Because of = () =>
    {
        output = Cryptographic.Decrypt(Cryptographic.Encrypt(input));
    };

    It should_decrypt_what_was_encrypted = () => input.ShouldEqual(output);

    static string input;
    static string output;
}

Is this a clean BDD unittest? Is there anything that can be improved? A couple of concerns from my side:

  1. I might be testing two things here, where I actually should test one. I have both Encrypt and Decrypt in the Because.
  2. The test involve a lot of copy and paste, all the test only differ by its input argument. Can or should this be improved, maybe by using some sort of row test, or a common base class or a Behaves clause instead? I mean readability is now pretty optimal but maintainability is not. If I optimize maintainability (DRY) I might be trading in readability.

How would you write the tests/specs for this?

Upvotes: 3

Views: 383

Answers (1)

Alexander Groß
Alexander Groß

Reputation: 10478

This unit test looks like a good starting point. I wonder if it would break if I implemented Encrypt and Decrypt such that it just returns its respective input. Currently, there's no need to encrypt anything which makes me wonder whether the test or the production code have been written first.

As a general rule, if you need to test pairs of input and output, I suggest to have a look at NUnit's TestCase et. al. BDD as a tool especially makes sense, but is not limited to, specifying system behavior. What you presented here is a single class that does not interact with any other part of the system. While I understand that BDD and the context/specification flavor might have helped to express the expected unit behavior, sometimes classic unit testing frameworks make more sense. That's especially true if you need a test run for tuples of input and output.

Upvotes: 1

Related Questions