Help me my first test - c#

I have created a Hello World program and I am new to C#, My program will print 100 words like that as follow
public static void Main(/*I forgot arguments*/)
{
string []s=new string [100];
foreach(string ss in s)
{
ss="Hello World";
Console.WriteLine("{0}\n",ss);
}
}
Could you show me step-by-step how to create a test for this program ? Does it need one ? I don't have an image of how testers do the test. Sorry I am stupid.
I think I have tried my best, no one ever find I find it unworthy to me not to get any help ? I don't need the class because I forgot the class long ago after the accident.

First of all, you can't (or - you shouldn't) test void methods. You are testing the output of the method - which Main does not have. Second thought: you cannot mock (simulate) an Console object. Read some tutorials about mock and mocking.
Sample method with sample test could look similar to this:
public class SimpleCalculator
{
public int SumTwoNumbers(int number1, int number2)
{
return number1 + number2;
}
}
[TestClass]
public class TestClass
{
[TestMethod]
public void Test_SimpleCalculator_SumTwoNumbers_CorrectValues()
{
// Arrange
SimpleCalculator calc = new SimpleCalculator();
// Act
int result = calc.SumTwoNumbers(5, 2);
// Assert
Assert.AreEqual(7, result);
}
}
Hope this helped a little.

Why would you need a test for this? What would you be testing for? Instead of how to test the code I'd be looking at how you can make it better.
Have a look at the Main below.
public static void Main(/*I forgot arguments*/)
{
for(var i = 0; i < 100; i++)
{
Console.WriteLine("Hello World");
}
}
Note, you don't use the array you create so there is no need to create it. Use a for loop when you know exactly how many times you need to loop. Also, there is no to format your string if you are not concating it with other strings.

Flush the above code to a method than having it in the main. Then refer to some unit test cases documents (If unit testing is what your looking for) here http://www.nunit.org/index.php?p=quickStart&r=2.5.10

Related

Unit Testing a Basic c# application with repository

I have a basic .NET application that I am being asked to write a unit test for, but unit tests have always confused me.
This application has two repositories (FoodRepository and DrinkRepository) that return data from a hardcoded list.
Here's the Program.cs:
public static void Main(string[] args)
{
var foodSvc = new FoodService();
var foodId = 12;
var grade = 98.2d;
foodSvc.UpdateFoodGrade(foodId, grade);
}
which calls:
public void UpdateFoodGrade(int foodId, double grade)
{
var foodRepo = new FoodRepository();
var food = foodRepo.GetFood(foodId);
food.Grade = grade;
if (!food.IsPassed)
{
var drinkRepository = new DrinkRepository();
var drink = drinkRepository.GetDrink(foodId);
if (grade >= drink.MinimumPassingGrade)
{
food.IsPassed = true;
}
else
{
food.IsPassed = false;
}
}
}
My question is, what unit test(s) typically would someone do here for this? And, can I get some examples?
Been googling and grinding on this, but the concept continues to escape me.
I've historically used full integration tests in test environments, and not really done unit tests.
If anyone needs more of the code to help with this please let me know. I'm super stuck.
Thanks
UPDATE:
I've gotten a lot further thanks to below, but I am still stuck on the rest of the test. Here's what my updated service looks like:
public class FoodService
{
private readonly FoodRepository _foodRepo;
private readonly DrinkRepository _drinkRepository;
public FoodService(FoodRepository foodRepo, DrinkRepository drinkRepository)
{
_foodRepo = foodRepo;
_drinkRepository = drinkRepository;
}
public void UpdateFoodGrade(int foodId, double grade)
{
var food = _foodRepo.GetFood(foodId);
food.Grade = grade;
if (!food.IsPassed)
{
var drink = _drinkRepository.GetDrink(foodId);
if (grade >= drink.MinimumPassingGrade)
{
food.IsPassed = true;
}
else
{
food.IsPassed = false;
}
}
}
}
Updated Main:
public class Program
{
public static void Main(string[] args)
{
var foodRepository = new FoodRepository();
var drinkRepository = new DrinkRepository();
var foodSvc = new FoodService(foodRepository, drinkRepository);
var foodId = 12;
var grade = 98.2d;
foodSvc.UpdateFoodGrade(foodId, grade);
}
}
Test So far (I have no idea what to do next)
[TestMethod]
public void UpdateFoodGrade_Test()
{
//Arrange
var foodId = 12;
var grade = 98.2d;
var expected = true;
var food = new Food() { FoodId = foodId };
var drink = new Drink() { DrinkId = foodId };
var foodRepositoryMock = new Mock<FoodRepository>();
foodRepositoryMock.Setup(m => m.GetFood(foodId)).Returns(food).Verifiable();
var drinkRepositoryMock = new Mock<DrinkRepository>();
drinkRepositoryMock.Setup(m => m.GetDrink(foodId)).Returns(drink).Verifiable();
var foodService = new FoodService(foodRepositoryMock.Object, drinkRepositoryMock.Object);
//Act
var actual = foodService.UpdateFoodGrade(foodId, grade);
//Assert
foodRepositoryMock.Verify();
drinkRepositoryMock.Verify();
Assert.AreEqual(expected, actual);
}
}
EDIT 2:
I went ahead and refactored in the interfaces, etc. Here's how it shook out:
[TestMethod]
public void UpdateLessonGrade_IsPassingGrade()
{
//Arrange
var lessonId = 12;
var lesson = new Lesson() { LessonId = lessonId };
var module = new Module() { ModuleId = lessonId };
var lessonRepositoryMock = new Mock<ILessonRepository>();
lessonRepositoryMock.Setup(x => x.GetLesson(lessonId)).Returns(lesson);
var moduleRepositoryMock = new Mock<IModuleRepository>();
moduleRepositoryMock.Setup(x => x.GetModule(lessonId)).Returns(module);
var lessonService = new LessonService(lessonRepositoryMock.Object, moduleRepositoryMock.Object);
//Act
lessonService.UpdateLessonGrade(12, 98.2d);
//Assert
Assert.IsTrue(lesson.IsPassed); // assuming it should pass in this condition
Assert.AreEqual(98.2d, lesson.Grade); // expected Lesson Grade should be what you expected the grade to be after you call UpdateLessonGrade
}
I'm on a mobile device right now, I can try to update the answer later this weekend, but this should get you started.
Refactor your method to use instance variables instead of direct instantiation in the method. Add them as parameters to your constructor. In the main method create your repository instances and pass them to the service constructor.
Now you can use something like Moq or the in memory provider for entity framework.
As for what to test, basically test every piece of branching logic. At a minimum, each piece of an if statement and the else conditions. You should also test what happens when your repository objects don't find what you're looking for (e.g. returns null). Offhand, I'm counting at least six tests.
Update: Bravo! Looking at your updated code in the question, everything is on the right track.
In your test method, you'll want to add:
var foodService = new FoodService(foodRepositoryMock.Object, drinkRepositoryMock.Object);
That will initialize your service with the mock objects.
Then you'll want to call your service with test parameters like:
foodService.UpdateFoodGrade(12, 98.2d);
The last part is check your food object using asserts like:
Assert.IsTrue(food.IsPassed) // assuming it should pass in this condition
Assert.Equals(98.2d, food.Grade); // expectedFoodGrade should be what you expected the grade to be after you call UpdateFoodGrade
It looks like you'll also need to flesh out the instance of your Drink object a little bit more. You need to specify a value for MinimumPassingGrade since it's used to drive the decision logic in your if statement, for example, if you want the food.IsPassed = true to trigger, you would instantiate the drink object like so:
var drink = new Drink() { DrinkId = foodId, MinimumPassingGrade = 50.0d };
You would create test methods for each of the other various test cases, failed the minimum, when it's equal to the score, if you can't find the food in the food repo, or the drink in the drink repo, etc.
One other note, you only need to worry about Verifiable mocks when you need to know that a method was/wasn't called. For these tests, I probably wouldn't verify that methods were called (creates tighter coupling between your test and the implementation vs. the behavior). You'd want to verify that the methods were called only if something in your service code truly depends on knowing that it was called. e.g. if you're using Entity Framework and you wanted to make sure you didn't forget to call SaveChanges().
Indeed, such code can't be "normally" unit-tested without preliminary refactoring. But you still have one (bit dirty) option: Shims mechanism of MS Fakes Library.
It allows you to substitute any method or property of any type (including static, non-public and system) with any arbitrary code. In your case you may create a ShimsContext in you test method, and give some fake behavior for FoodRepository.GetFood() and DrinkRepository.GetDrink() methods, for example, empty body doing nothing. So, when your test runs, your stub code gonna be executed instead of the actual code of repository classes. So you will test only Service code without executing code of repositories.
You may check this article for quick introduction to the library.
And please keep in mind that Shims is not a way of good unit-testing, It is just a tool to deal with such non-testable code in case when you absolutely need to unit-test it somehow without changing the code itself.

Text to Speech C#

So I'm just a uni student who's enjoying programming (1st year) and I've decided to try out some new features.
I came across the speech synthesizer and its reallt interesting, but i have one problem.
Say if I said
Console.WriteLine("Hello");
Is there a way that I could get the program to say that without having to add
Console.WriteLine("Hello");
s.Speak("Hello");
?
Like I'm wondering if I am able to have my program speak whatever I type without adding extra code
Cheers
There is no way you could do that. But what you can try is creating a static method that takes a string value and prints "Hello" on to the console and use the TTS engine, like
static void PrintAndSpeak(string message)
{
Console.WriteLine(message);
s.Speak(message);
}
And then use the method inside the entry point:
PrintAndSpeak("Hello");
You could create a method that would take in your string. That method would print and read the message.
Example (pseudocode)
public void writeAndTalk(string message){
Console.WriteLine(message);
s.Speak(message);
}
And you then use the method wherever you like.
You could create a type to do this for you. Something like:
public class TextAndSpeech
{
private readonly WhateverSIs s;
public TextAndSpeech(WhateverSIs s)
{
this.s = s;
}
public Spurt(string message)
{
Console.WriteLine(message);
s.Speak(message);
}
}
I have no idea what type s is that you're using, so replace WhateverSIs with the actual type.
Using it would look something like:
var spurter = new TextAndSpeech(new WhateverSIs());
spurter.Spurt("Hello");
spurter.Spurt("Another thing.");

How to add to a class a string with two integers and show the sum

Greeting fellow programmers!
I am currently studying software development (I started not a month ago) and I have a problem that needs a solution. Underneath you can find the code and as you can see, the method WriteNumber needs help. I need to write the code in a way that when I run the program, on the console screen the following two lines will be shown:
Hello World!
81
The Main method code cannot be changed and also I cannot add more methods to the class Calculator so the code needs to be done only within the WriteNumbers method. I have tried a lot of things but I am still grasping how everything works so any help is welcome! Thank you in advance for your time.
Namespace CalculatorTest
{
class Calculator
{
public static string WriteText (string input)
{
return "" + input;
}
public static string WriteNumber()
{
}
}
class Program
{
static void Main(string[] args)
{
string s = Calculator.WriteText("Hello World!");
Console.WriteLine(s);
string n = Calculator.WriteNumber(53 + 28);
Console.WriteLine(n);
Console.Read();
}
}
Not to do your homework for you to just be copied/pasted, hopefully I can give you some hints...
Notice how the method is being invoked:
Calculator.WriteNumber(53 + 28)
The 53 + 28 part happens first, then the result of that operation is passed to the method. That result, naturally, is 81. What's important about that is its type, which is an integer.
So, reasonably, the method signature needs to accept an int as a parameter. This would be done very similarly to how the other method accepts a string as a parameter:
public static string WriteText(string input)
What, then, does that method need to do with that input? Well, it's only a single value, so there aren't any calculations to be performed on it. It would appear that the method simply needs to return the value as a string. (It's your homework so you tell me, is that correct?)
This can be done with exactly two things:
Calling .ToString() on the value
Using the return keyword to return the result of that operation
(Note: The .ToString() operation does something very intuitive on value types, such as int or double or bool. As you progress into using reference types, you're going to find that it does something very different. Any time you have a custom class on which you want to call .ToString(), you'll need to override the .ToString() method on that class first.)
Please read David's answer, it's important that you make the effort to understand why this works the way it does. That being said:
public static string WriteNumber(int number)
{
return number.ToString();
}
Thank you all for your valuable input but special thanks to David because he showed where I made my error. I forgot that the two numbers in the main function will be summed up FIRST and THEN forwarded to the method in the class Calculator. After that got cleared up, it was easy to understand what to do (basically adjust the type of the input parameter to int).
namespace CalculatorTest
{
class Calculator
{
public static string WriteText (string input)
{
return "" + input;
}
public static string WriteNumber(int sumOfNumbers)
{
return "" + sumOfNumbers;
}
}
class Program
{
static void Main(string[] args)
{
string s = Calculator.WriteText("Hello World!");
Console.WriteLine(s);
string n = Calculator.WriteNumber(53 + 28);
Console.WriteLine(n);
Console.Read();
}
}
}

visual studio 2010 c# unit tests

Trying to create unit tests for my methods and can't seem to get the configuration right.
I go New Test -> Unit Test Wizard -> Pick my method -> fill in test method values but I always get Assert.Inconclusive failed. Verify the correctness of this test method.
Here is a sample method:
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
}
public int Mult(int a, int b)
{
return a * b;
}
}
}
and the test method:
[TestMethod()]
public void MultTest()
{
Program target = new Program(); // TODO: Initialize to an appropriate value
int a = 4; // TODO: Initialize to an appropriate value
int b = 5; // TODO: Initialize to an appropriate value
int expected = 20; // TODO: Initialize to an appropriate value
int actual;
actual = target.Mult(a, b);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method.");
}
Seems straight forward enough, but am I missing something trivial?
The Assert.Inconclusive is mainly a marker to tell you that you need to right your own verification steps for the test method. In other words, for what you are doing it can be removed as you have added your own Assertion.
It could also be used, if there is some logic in your test that prevents the full running of your test. So, if, for example, you couldn't create the object you were trying to test for some reason.
sure you do :
Assert.Inconclusive("Verify the correctness of this test method.");
Your test says inconclusive therfore the result of the test is inconclusive.. You should use this syntax "Assert.Inconclusive" only to cover edge cases you are really aware of.
AFAIC, I never use it.

How can I use NUnit to test a method with out or ref parameters?

If I have a function which accepts an out parameter and accepts an input form console -
public void Test(out int a)
{
a = Convert.ToInt16(Console.ReadLine());
}
How can I accept an input using Console.Readline() during NUnit test? How can I use NUnit to test this method?
I tried using this code for my NUnit test case -
[TestCase]
public void test()
{
int a = 0;
ClassAdd ad = new ClassAdd();
ad.addition(out a);
//a should be equal to the value I input through console.Readline()
Assert.AreEqual(<some value I input>, a, "test");
}
how can I test a method which accepts an out parameter and also accepts an user input from Console?
You can use the SetIn method of System.Console to set the the input source:
StringReader reader = new StringReader("some value I input" + Enivronment.NewLine);
Console.SetIn(reader);
int a = 0;
ClassAdd ad = new ClassAdd();
ad.addition(out a);
Assert.AreEqual(<some value I input>, a, "test");
EDIT: To test multiple values, just separate each input with a new line:
string[] lines = new[] { "line1", "line2" };
StringReader input = new StringReader(String.Join(Environment.NewLine, lines));
Console.SetIn(input);
string input1 = Console.ReadLine(); //will return 'line1'
string input2 = Console.ReadLine(); //will return 'line2'
There are 2 slightly different issues combined here.
You want to test a method that returns a value in an out parameter. This is actually quite trivial and is hardly different from a method that returns its value as a normal function.
You want to test a method that reads input form the console. This one is quite a bit trickier, and goes a little into the design of the object you're trying to test. The problem is that the "Console" is a global object, and that immediately makes it more difficult to test.
The craziest thing to note is that you want to test a method that takes input from the console. I.e. this implies user interaction. This is hardly the way to go about "automated testing" don't you think?
In answer to #2, I suggest you look at some of Misko Hevery's articles and videos on writing testable code.
http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/
For a brief summary specfic to your problem:
MethodToTest currently wants input from the console.
The class that holds MethodToTest should take an "input stream" in its constructor. (This is a technique called dependency injection.)
In production code, your class will be created with the normal "Console" as its input stream.
In test code, the class will be constructed with a Mock input stream that will feed values controlled by the test.
In this way your test can be automated, and well controlled in terms of inputs; and therefore expected outputs.
Bare Bones Sample Code
[TestCase]
public void test()
{
<use appropriate type here> MockInputStream = new ...;
ClassToTest testClass = new ClassToTest(MockInputStream);
int Actual = 0;
MockInputStream.PutNextInput("4");
ClassToTest.MethodToTest(out Actual);
Assert.AreEqual(4, Actual, "MockInputStream placed 4 as the next value to read");
}

Categories