When creating a unit test have you end up spending more time writing boilerplate code to perform your test than you spend actually writing. GennyMcGenFace's goal is to save you time when writing unit tests! Generates random values for classes in your unit tests.
Generating random values for a class example:
Sample test outputThis is a sample of what Genny will generate for you. I have added some commented to explain the anatomy. C# Edit|Remove csharp using Microsoft.VisualStudio.TestTools.UnitTesting;using TestyMcTestFace;using System;using TestyMcTestFace.Models; //it adds the using statements needed by the testsusing System.Threading.Tasks;using System.Collections.Generic;using NSubstitute;namespace TestyMcTestFace{ [TestClass] public class TestyMcTestFace_AnotherClassTests { //it generates the interfaces here so we can use them in the tests private ISomeProcess _iSomeProcess; private ILoggingProcess _iLoggingProcess; private AnotherClass _testTarget; [TestInitialize] public void Init() { _iSomeProcess = Substitute.For<ISomeProcess>(); _iLoggingProcess = Substitute.For<ILoggingProcess>(); //_testTarget is where we declare the class you selected to generate tests for _testTarget = new AnotherClass(_iSomeProcess, _iLoggingProcess); //it looks at what functions are in the interfaces class and generates valid data to be returned by them _iSomeProcess.SomeAsyncFunction(Arg.Any<string>()).Returns(Task.FromResult("Omovs")); _iSomeProcess.GetMultipleSimpsons(Arg.Any<string>()).Returns(GetSimpsonMemberList()); _iSomeProcess.GetHomerAsDuffMan(Arg.Any<TestyMcTestFace.Models.SimpsonMember>()).Returns(GetDuffMan()); _iSomeProcess.SomeFunction(Arg.Any<TestyMcTestFace.Models.SimpsonMember>(), Arg.Any<string>(), Arg.Any<int>()).Returns("Virosis"); _iLoggingProcess.LogError(Arg.Any<string>(), Arg.Any<System.Exception>()).Returns("Uveitic"); _iLoggingProcess.LogMultipleError(Arg.Any<List<string>>(), Arg.Any<List<System.Exception>>()).Returns("Muscose"); } //For each function inside of "AnotherClass" we have generated a unit test for that function //"AnotherClass" has 5 functions, we have generated a test for each function here [TestMethod] public void FunFunctionTest() { var param1 = GetDuffManList(); //"FunFunction" requires an input object List<DuffMan>, here we have generated that for you var res = _testTarget.FunFunction(param1); Assert.IsNotNull(res); } [TestMethod] public void StaticFunctionTestTest() { var param1 = GetHouse(); var res = AnotherClass.StaticFunctionTest(param1, 73407166, "Nongraded"); Assert.IsNotNull(res); } [TestMethod] public async Task SomeAsyncFunctionTest() { var param1 = GetHouse(); var res = await _testTarget.SomeAsyncFunction(param1); Assert.IsNotNull(res); } [TestMethod] public async Task SomeAsyncTaskNoReturnTypeTest() { await _testTarget.SomeAsyncTaskNoReturnType(75252854); } [TestMethod] public void SomeFunctionTest() { var param1 = GetDuffMan(); _testTarget.SomeFunction(param1); } //At the bottom of the generated code we have objects that are used by Interfaces and Functions used throughout the test. //We keep them at the bottom in static functions so we can reuse them in other tests and we only have to write out the valid data once private static TestyMcTestFace.Models.House GetHouse() { return new TestyMcTestFace.Models.House() { SomeTuple = new System.Tuple<string, int>("Rigorousnesses", 93369728) {}, Line1 = "Katana", Line2 = "Apimanias", City = "Longhouse", State = "Dekko", Zip = "Responsions", Country = "Fuzziest" }; } //Yes, I realize the random values can be pretty ridiculous //but the goal here is to save you time. Some of these might not even need to be changed //And if they do need to be changed, it takes a lot less time to fill in a valid value for some fields then it would take to write out this entire class. //Picture how long this would take if we had an object with 100 fields? private static TestyMcTestFace.Models.DuffMan GetDuffMan() { return new TestyMcTestFace.Models.DuffMan() { BeersToday = 12712378, FavBeers = new String[] { "Maceral" }, Age = 45182466, Houses = new TestyMcTestFace.Models.House[] { new TestyMcTestFace.Models.House() { SomeTuple = new System.Tuple<string, int>("Natation", 64155858) {}, Line1 = "Sexagesimal", Line2 = "Cressy", City = "Pinwale", State = "Invigilator", Zip = "Folkies", Country = "Hypostatizes" } } }; } private static System.Collections.Generic.List<TestyMcTestFace.Models.DuffMan> GetDuffManList() { return new List<TestyMcTestFace.Models.DuffMan>() { new TestyMcTestFace.Models.DuffMan() { BeersToday = 73427576, FavBeers = new String[] { "Sopping" }, Age = 87551091, Houses = new TestyMcTestFace.Models.House[] { new TestyMcTestFace.Models.House() { SomeTuple = new System.Tuple<string, int>("Liposuck", 28022586) {}, Line1 = "Meltability", Line2 = "Hymenophores", City = "Devvels", State = "Correctitude", Zip = "Dukkah", Country = "Incuses" } } } }; } private static System.Collections.Generic.List<TestyMcTestFace.Models.SimpsonMember> GetSimpsonMemberList() { return new List<TestyMcTestFace.Models.SimpsonMember>() { new TestyMcTestFace.Models.SimpsonMember() { Gender = TestyMcTestFace.Enums.Gender.Male, FirstName = "Stickle", LastName = "Mesencephalon", CatchPhrase = "Casuistic", House = new TestyMcTestFace.Models.House() { SomeTuple = new System.Tuple<string, int>("Proterandries", 59930647) {}, Line1 = "Befringe", Line2 = "Rorquals", City = "Betumbled", State = "Thrills", Zip = "Trigged", Country = "Populousnesses" }, ShoeSize = 5993, SomethingElse = "Amphictyonic" } }; } }} using Microsoft.VisualStudio.TestTools.UnitTesting; using TestyMcTestFace; using System; using TestyMcTestFace.Models; //it adds the using statements needed by the tests using System.Threading.Tasks; using System.Collections.Generic; using NSubstitute; namespace TestyMcTestFace { [TestClass] public class TestyMcTestFace_AnotherClassTests { //it generates the interfaces here so we can use them in the tests private ISomeProcess _iSomeProcess; private ILoggingProcess _iLoggingProcess; private AnotherClass _testTarget; [TestInitialize] public void Init() { _iSomeProcess = Substitute.For<ISomeProcess>(); _iLoggingProcess = Substitute.For<ILoggingProcess>(); //_testTarget is where we declare the class you selected to generate tests for _testTarget = new AnotherClass(_iSomeProcess, _iLoggingProcess); //it looks at what functions are in the interfaces class and generates valid data to be returned by them _iSomeProcess.SomeAsyncFunction(Arg.Any<string>()).Returns(Task.FromResult("Omovs")); _iSomeProcess.GetMultipleSimpsons(Arg.Any<string>()).Returns(GetSimpsonMemberList()); _iSomeProcess.GetHomerAsDuffMan(Arg.Any<TestyMcTestFace.Models.SimpsonMember>()).Returns(GetDuffMan()); _iSomeProcess.SomeFunction(Arg.Any<TestyMcTestFace.Models.SimpsonMember>(), Arg.Any<string>(), Arg.Any<int>()).Returns("Virosis"); _iLoggingProcess.LogError(Arg.Any<string>(), Arg.Any<System.Exception>()).Returns("Uveitic"); _iLoggingProcess.LogMultipleError(Arg.Any<List<string>>(), Arg.Any<List<System.Exception>>()).Returns("Muscose"); } //For each function inside of "AnotherClass" we have generated a unit test for that function //"AnotherClass" has 5 functions, we have generated a test for each function here [TestMethod] public void FunFunctionTest() { var param1 = GetDuffManList(); //"FunFunction" requires an input object List<DuffMan>, here we have generated that for you var res = _testTarget.FunFunction(param1); Assert.IsNotNull(res); } [TestMethod] public void StaticFunctionTestTest() { var param1 = GetHouse(); var res = AnotherClass.StaticFunctionTest(param1, 73407166, "Nongraded"); Assert.IsNotNull(res); } [TestMethod] public async Task SomeAsyncFunctionTest() { var param1 = GetHouse(); var res = await _testTarget.SomeAsyncFunction(param1); Assert.IsNotNull(res); } [TestMethod] public async Task SomeAsyncTaskNoReturnTypeTest() { await _testTarget.SomeAsyncTaskNoReturnType(75252854); } [TestMethod] public void SomeFunctionTest() { var param1 = GetDuffMan(); _testTarget.SomeFunction(param1); } //At the bottom of the generated code we have objects that are used by Interfaces and Functions used throughout the test. //We keep them at the bottom in static functions so we can reuse them in other tests and we only have to write out the valid data once private static TestyMcTestFace.Models.House GetHouse() { return new TestyMcTestFace.Models.House() { SomeTuple = new System.Tuple<string, int>("Rigorousnesses", 93369728) {}, Line1 = "Katana", Line2 = "Apimanias", City = "Longhouse", State = "Dekko", Zip = "Responsions", Country = "Fuzziest" }; } //Yes, I realize the random values can be pretty ridiculous //but the goal here is to save you time. Some of these might not even need to be changed //And if they do need to be changed, it takes a lot less time to fill in a valid value for some fields then it would take to write out this entire class. //Picture how long this would take if we had an object with 100 fields? private static TestyMcTestFace.Models.DuffMan GetDuffMan() { return new TestyMcTestFace.Models.DuffMan() { BeersToday = 12712378, FavBeers = new String[] { "Maceral" }, Age = 45182466, Houses = new TestyMcTestFace.Models.House[] { new TestyMcTestFace.Models.House() { SomeTuple = new System.Tuple<string, int>("Natation", 64155858) {}, Line1 = "Sexagesimal", Line2 = "Cressy", City = "Pinwale", State = "Invigilator", Zip = "Folkies", Country = "Hypostatizes" } } }; } private static System.Collections.Generic.List<TestyMcTestFace.Models.DuffMan> GetDuffManList() { return new List<TestyMcTestFace.Models.DuffMan>() { new TestyMcTestFace.Models.DuffMan() { BeersToday = 73427576, FavBeers = new String[] { "Sopping" }, Age = 87551091, Houses = new TestyMcTestFace.Models.House[] { new TestyMcTestFace.Models.House() { SomeTuple = new System.Tuple<string, int>("Liposuck", 28022586) {}, Line1 = "Meltability", Line2 = "Hymenophores", City = "Devvels", State = "Correctitude", Zip = "Dukkah", Country = "Incuses" } } } }; } private static System.Collections.Generic.List<TestyMcTestFace.Models.SimpsonMember> GetSimpsonMemberList() { return new List<TestyMcTestFace.Models.SimpsonMember>() { new TestyMcTestFace.Models.SimpsonMember() { Gender = TestyMcTestFace.Enums.Gender.Male, FirstName = "Stickle", LastName = "Mesencephalon", CatchPhrase = "Casuistic", House = new TestyMcTestFace.Models.House() { SomeTuple = new System.Tuple<string, int>("Proterandries", 59930647) {}, Line1 = "Befringe", Line2 = "Rorquals", City = "Betumbled", State = "Thrills", Zip = "Trigged", Country = "Populousnesses" }, ShoeSize = 5993, SomethingElse = "Amphictyonic" } }; } } }
The generated tests will need Nsubstitute nuget package if interfaces are used. Install-Package NSubstitute
GennyMcGenFace's goal is not to generate 100% of the unit test, but to automate as much as possible. |