How to test function returns IEnumerable<Integer> - c#

I'm trying to test a function
public static IEnumerable<Integer> Divisors(Integer n)
{
int max = (int)System.Math.Sqrt(n);
if (n != 0)
yield return 1;
for (int i = 2; i <= max; i++)
if (n % i == 0)
yield return i;
}
and I need to write a test function like
[Test]
public void DivisorsTest()
{
Integer n = 0;
IEnumerable<Integer> expected = 0 ; //error
IEnumerable<Integer> actual;
actual = Science.Mathematics.NumberTheoryFunctions.Divisors(n);
Assert.AreEqual(expected, actual);
}
How can I modify this line to test the output I need to test the returning values which are not just a zero

There are various tricks to checking entire collections. It looks like for an input of zero, you don't want to have any values returned (i.e. an empty set), so you could do this:
Assert.IsFalse(actual.Any()); // There should not be any elements returned
For more complex outputs, it is often easier to put the result into an array, and check the results by index like this:
var results = actual.ToArray();
Assert.AreEqual(5, results.Count);
Assert.AreEqual(1, results[0]);
Assert.AreEqual(2, results[1]);
// etc.

Couldn't you use something like this (sorry, it needs Linq):
[Test]
public void DivisorsTest()
{
int n = 0;
int expected = 0; //error
IEnumerable<Integer> actual;
actual = Science.Mathematics.NumberTheoryFunctions.Divisors(n);
Assert.IsTrue(actual.All(x => x != expected));
}

You could also initialize expected to an empty enumerable (i.e., zero elements) like this
IEnumerable<int> expected = System.Linq.Enumerable.Empty<int>();
MSDN Reference for Enumerable

I often use something like that:
var expected = new int[] { /* expected values */ };
var actual = Science.Mathematics.NumberTheoryFunctions.Divisors(n);
Assert.IsTrue(expected.SequenceEquals(actual));
The drawback is that the assertion default error message isn't very descriptive:
Expected: True
But was: False
Instead, you can use CollectionAssert.AreEquivalent, which gives a more detailed error message, but it's not ideal either... If you use a Linq query, the message can look like that:
Expected: equivalent to < 0, 1, 3, 4, 6, 7, 9, 10 >
But was: <System.Linq.Enumerable+<WhereIterator>d__0`1[System.Int32]>
(at least with NUnit 2.4.8, perhaps I should upgrade to a newer version...)

OK, thanks everybody for your answers and here is what i did using your answers
the test functions will be :
1- when you expect that the function won't return any value
[Test]
public void DivisorsTest_01()
{
Integer n = 0;
IEnumerable<Integer> actual;
actual = Science.Mathematics.NumberTheoryFunctions.Divisors(n);
Assert.IsFalse(actual.Any()); // There should not be any elements returned so empty
}
2- all what you need is to convert the o/p into an array and use it :
[Test]
public void DivisorsTest_03()
{
Integer n = 9;
Integer[] expected = new Integer[3] { 1,3,9 };
IEnumerable<Integer> actual;
actual = Science.Mathematics.NumberTheoryFunctions.Divisors(n);
var actual1 = actual.ToArray();
Assert.AreEqual(expected[0], actual1[0]);
Assert.AreEqual(expected[1], actual1[1]);
Assert.AreEqual(expected[2], actual1[2]);
}
3- sometimes you expect the output will be exception so don't forget to write:
[Test]
[ExpectedException]
before the function.
thanks again everybody

Related

Testing an infinite sequence with NUnit, but only a finite sequence must be checked

I have an Extension Method that extract the numbers in a list of strings (bbb1, da21ds, dsa231djsla90 ==> 1, 21, 23190):
public static int[] GetContainedNumbers(this string[] source)
{
if (source == null) throw new ArgumentNullException();
int[] result = new int[] {};
foreach (var s in source)
{
string onlyNumbers = new String(s.Where(Char.IsDigit).ToArray());
if (String.IsNullOrEmpty(onlyNumbers)) throw new ArgumentException();
int extractedNumber = Int32.Parse(onlyNumbers);
result = result.Concat(new int[] { extractedNumber }).ToArray();
}
return result;
}
I need to make a test with NUnit. The request is to make a test with an infinite sequence of strings (a1z, a2z, a3z, ...), but the output only needs to check the first 100 numbers.
Currently I have no idea what I'm supposed to do. My starting idea was to create a test like this:
int[] expectedResult = Enumerable.Range(0, 99).ToArray();
string[] source = new string[] {};
int n = 0;
while (true)
{
if (n == 99) break;
source = source.Concat(new string[] { "a" + n + "z" }).ToArray();
n++;
}
Assert.AreEqual(expectedResult, source.GetContainedNumbers());
But it doesn't really make sense since the array is finite and not infinite.
I don't know what it means to create an infinite list of things and how I should create it nor testing it.
I can edit the Extension Method if needed. Thanks in advance for any help and sorry if my english is quite broken.
The first task is to make the Extension method itself, which I have resolved above. It can be modified, but it must resolve this piece of code (which I can't edit):
foreach (var d in new[] { "1qui7", "q8u8o", "-1024", "0q0ua0" }.GetContainedNumbers())
{
Console.WriteLine("{0}, ", d);
var strings = new [ ] { "1qui7" , " q8u8o " , " −1024" , " 0 q0ua0 " };
}
Expected output: 17, 88, 1024, 0,
I believe the purpose of this exercise is to investigate lazy evaluation.
Currently your method accepts a string[] and returns an int[] - but there's nothing in the question that says it has to do that.
If instead you were to write an extension method accepting an IEnumerable<string> and returning an IEnumerable<int>, then you could accept an infinite sequence of elements and return a corresponding infinite sequence of outputs, that is lazily evaluated: when the caller requests the next output element, you in turn request the next input element, process it, and yield an output. C# makes all of this quite straightforward with iterator blocks.
So I would expect a method like this:
public static IEnumerable<int> GetContainedNumbers(IEnumerable<string> source)
{
foreach (string inputElement)
{
int outputElement = ...; // TODO: your logic here
yield return output;
}
}
Now to test this, you can either use iterator blocks again to generate genuinely infinite sequences, or you could test against an effectively infinite sequence using LINQ, e.g.
IEnumerable<string> veryLargeInput = Enumerable
.Range(0, int.MaxValue)
.Select(x => $"a{x}z");
The truly infinite version might be something like:
IEnumerable<string> infiniteSequence = GetInfiniteSequence();
...
private static IEnumerable<string> GetInfiniteSequence()
{
int value = 0;
while (true)
{
yield return $"x{value}z";
// Eventually this will loop round from int.MaxValue to
// int.MinValue. You could use BigInteger if you really wanted.
value++;
}
}
When testing the result, you'll want to take the first 100 elements of the output. For example:
var input = GetInfiniteSequence(); // Or the huge Enumerable.Range
var output = input.GetContainedNumbers(); // This is still infinite
var first100Elements = output.Take(100).ToList();
// Now make assertions against first100Elements

How to get enum by index with different set values? [duplicate]

I need to get the numeric position of an enum in its definition.
Consider the following enum - it is used for bit fields but the status names
would be useful if they had the values on the right that I have commented.
[Flags]
public enum StatusFlags
{
None = 0, // 0 -- these commented indexes are the numbers I also would like
Untested = 1, // 1 to associate with the enum names.
Passed_Programming = 2, // 2
Failed_Programming = 4, // 3
// ... many more
}
I have created a static method as follows, which works for what I want.
public static int GetStatusID(this StatusFlags flag)
{
int i = 0;
foreach (StatusFlags val in Enum.GetValues(typeof(StatusFlags)))
{
if (flag == val) break;
i++;
}
return i;
}
It is used like this:
StatusFlags f = StatusFlags.Failed_Programming;
// I want the position i.e value of 3 not the value the enum is associated with i.e 4
int Index = f.GetStatusID();
Is there is a better way to do this?
How about using attributes on your enum? Something like this:
[Flags]
public enum StatusFlags
{
[Index=0]
None = 0,
[Index=1]
Untested = 1,
[Index=2]
Passed_Programming = 2,
[Index=3]
Failed_Programming = 4,
// ... many more
}
Then you can the index value of your enum like this:
var type = typeof(StatusFlags);
var statusFlag = type.GetMember(StatusFlags.Untested.ToString());
var attributes = statusFlag [0].GetCustomAttributes(typeof(IndexAttribute),false);
var index = int.Parse(((IndexAttribute)attributes[0]).Index); //if you need an int value
A deleted answer here suggested something that resembled
public static int GetStatusID(this StatusFlags flag)
{
return Array.IndexOf(Enum.GetValues(typeof(StatusFlags)), flag);
}
and was just missing the syntactical point that IndexOf is a static function in the Array class, not an extension method. I like it though for brevity.
You could do this:
public static int GetStatusID(this StatusFlags flag)
{
return
Enum
.GetValues(typeof(StatusFlags))
.Cast<StatusFlags>()
.Select((f, n) => new { f, n })
.Where(fn => fn.f == flag)
.Select(fn => fn.n)
.DefaultIfEmpty(0)
.First();
}
How about just using math? He says the flags go up in powers of 2
int GetStatusID(this StatusFlags flag)
{
if (((int)flag) == 0) return 0;
return (Math.Log((double)flag) / Math.Log(2D)) + 1;
}
If each flag has only 1 bit set like that then the index is just Math.Log2((int)flag) + 1. However Math.Log2 is a floating-point operation and is very slow so don't use it
If you're using .NET Core then there are BitOperations.Log2 and BitOperations.TrailingZeroCount which map directly to hardware instructions like TZCNT/BSF in x86 or CLZ in ARM, hence are much more efficient and the result is like this
public static int GetStatusID(this StatusFlags flag)
{
if ((int)flag == 0)
return 0;
return BitOperations.Log2((int)flag);
// or return BitOperations.TrailingZeroCount((int)flag) + 1;
}
If you're using an older .NET framework then calculate see the way to calculate integer log2 quickly in these questions
What's the quickest way to compute log2 of an integer in C#?
Fastest implementation of log2(int) and log2(float)
Fast way of finding most and least significant bit set in a 64-bit integer

Returning an Array Manipulates Original Value in C#

This is my first question on the site and I am sure I'll find my answer here.
For school, I was trying to do some basic C# coding for a challenge that was given to us.
Here is the problem:
Normally when I pass a value through a method I don't run into issues. Like so:
static void Main(string[] args)
{
// Declare Integer
int originalInt = 20;
// Call the Method
int multipliedInt = Multiplication(originalInt);
// Prompt
Console.WriteLine("Original: {0} Modified: {1}", originalInt, multipliedInt);
}
// Method
static public int Multiplication(int original)
{
// Quik Maffs
int modifiedValue = original * 2;
return modifiedValue;
}
The above example works just fine. The original value is 20 and the modified value is 40.
However, this changes when I attempt to do that with an array:
static void Main(string[] args)
{
// Declare Original Array
int[] originalArray = new int[] {1, 4, 6, 8, 12};
// Call Method
int[] multipliedArray = Multiplication(originalArray);
// Prompt
Console.WriteLine("Original: [{0}], Multiplied: [{1}]", String.Join(", ", originalArray), String.Join(", ", multipliedArray));
}
// Method
static public int[] Multiplication(int[] original)
{
// New Int
int[] modified = original;
// Loop
for (int i = 0; i < modified.Length; i++)
{
modified[i] *= 2;
}
return modified;
}
The code above returned the modified value twice. It seems like it modifies the original value as well.
Any idea why this is happening?
int is a value type. When you pass a value type to a method, you pass a copy of the value.
Arrays are reference types. When you pass a reference type to a method, you pass a copy of the reference... but both the copy and original still refer to the same object.
Now it seems you may have understood this much, because of this code:
(This is why I re-opened the question... the stock ref-vs-value answer wasn't gonna cut it here)
int[] modified = original;
However, the other thing that happens with reference types is assignments also only copy the reference. So modified and original in that snippet again refer to the same array object.
To fix this, you need to make an actual deep copy of the array. There are several ways to do this. I would tend to write the method this way:
static public IEnumerable<int> Multiplication(IEnumerable<int> original)
{
return original.Select(i => i * 2);
}
...and append a .ToArray() at the end of the method call if and only if I really need a full array (hint: very often it turns out you don't), like this:
int[] multipliedArray = Multiplication(originalArray).ToArray();
or like this:
var multipliedArray = Multiplication(originalArray);
But I understand there are a number of things here that aren't very familiar to a beginner. You might try something more like this:
static public int[] Multiplication(int[] original)
{
int[] modifed = new int[original.Length];
for (int i = 0; i < original.Length; i++)
{
modified[i] = original[i] * 2;
}
return modified;
}

How do I create an IComparer for a Nunit CollectionAssert test?

I wish to create the following test in NUnit for the following scenario: we wish to test the a new calculation method being created yields results similar to that of an old system. An acceptable difference (or rather a redefinition of equality) between all values has been defined as
abs(old_val - new_val) < 0.0001
I know that I can loop through every value from the new list and compare to values from the old list and test the above condition.
How would achieve this using Nunit's CollectionAssert.AreEqual method (or some CollectionAssert method)?
The current answers are outdated. Since NUnit 2.5, there is an overload of CollectionAssert.AreEqual that takes a System.Collections.IComparer.
Here is a minimal implementation:
public class Comparer : System.Collections.IComparer
{
private readonly double _epsilon;
public Comparer(double epsilon)
{
_epsilon = epsilon;
}
public int Compare(object x, object y)
{
var a = (double)x;
var b = (double)y;
double delta = System.Math.Abs(a - b);
if (delta < _epsilon)
{
return 0;
}
return a.CompareTo(b);
}
}
[NUnit.Framework.Test]
public void MyTest()
{
var a = ...
var b = ...
NUnit.Framework.CollectionAssert.AreEqual(a, b, new Comparer(0.0001));
}
Well there is method from the NUnit Framework that allows me to do tolerance checks on collections. Refer to the Equal Constraint. One uses the AsCollection and Within extension methods. On that note though I am not 100% sure regarding the implications of this statement made
If you want to treat the arrays being compared as simple collections,
use the AsCollection modifier, which causes the comparison to be made
element by element, without regard for the rank or dimensions of the
array.
[Test]
//[ExpectedException()]
public void CheckLists_FailsAt0()
{
var expected = new[] { 0.0001, 0.4353245, 1.3455234, 345345.098098 };
var result1 = new[] { -0.0004, 0.43520, 1.3454, 345345.0980 };
Assert.That(result1, Is.EqualTo(expected).AsCollection.Within(0.0001), "fail at [0]"); // fail on [0]
}
[Test]
//[ExpectedException()]
public void CheckLists_FailAt1()
{
var expected = new[] { 0.0001, 0.4353245, 1.3455234, 345345.098098 };
var result1a = new[] { 0.0001000000 , 0.4348245000 , 1.3450234000 , 345345.0975980000 };
Assert.That(result1a, Is.EqualTo(expected).AsCollection.Within(0.0001), "fail at [1]"); // fail on [3]
}
[Test]
public void CheckLists_AllPass_ForNegativeDiff_of_1over10001()
{
var expected = new[] { 0.0001, 0.4353245, 1.3455234, 345345.098098 };
var result2 = new[] { 0.00009900 , 0.43532350 , 1.34552240 , 345345.09809700 };
Assert.That(result2, Is.EqualTo(expected).AsCollection.Within(0.0001)); // pass
}
[Test]
public void CheckLists_StillPass_ForPositiveDiff_of_1over10001()
{
var expected = new[] { 0.0001, 0.4353245, 1.3455234, 345345.098098 };
var result3 = new[] { 0.00010100 , 0.43532550 , 1.34552440 , 345345.09809900 };
Assert.That(result3, Is.EqualTo(expected).AsCollection.Within(0.0001)); // pass
}
NUnit does not define any delegate object or interface to perform custom checks to lists, and determine that a expected result is valid.
But I think that the best and simplest option is writing a small static method that achieve your checks:
private const float MIN_ACCEPT_VALUE = 0.0001f;
public static void IsAcceptableDifference(IList collection, IList oldCollection)
{
if (collection == null)
throw new Exception("Source collection is null");
if (oldCollection == null)
throw new Exception("Old collection is null");
if (collection.Count != oldCollection.Count)
throw new Exception("Different lenghts");
for (int i = 0; i < collection.Count; i++)
{
float newValue = (float)collection[i];
float oldValue = (float)oldCollection[i];
float difference = Math.Abs(oldValue - newValue);
if (difference < MIN_ACCEPT_VALUE)
{
throw new Exception(
string.Format(
"Found a difference of {0} at index {1}",
difference,
i));
}
}
}
You've asked how to achieve your desired test using a CollectionAssert method without looping through the list. I'm sure this is obvious, but looping is exactly what such a method would do...
The short answer to your exact question is that you can't use CollectionAssert methods to do what you want. However, if what you really want is an easy way to compare lists of floating point numbers and assert their equality, then read on.
The method Assert.AreEqual( double expected, double actual, double tolerance ) releases you from the need to write the individual item assertions yourself. Using LINQ, you could do something like this:
double delta = 0.0001;
IEnumerable<double> expectedValues;
IEnumerable<double> actualValues;
// code code code
foreach (var pair in expectedValues.Zip(actualValues, Tuple.Create))
{
Assert.AreEqual(pair.Item1, pair.Item2, delta, "Collections differ.");
}
If you wanted to get fancier, you could pull this out into a method of its own, catch the AssertionException, massage it and rethrow it for a cleaner interface.
If you don't care about which items differ:
var areEqual = expectedValues
.Zip(actualValues, Tuple.Create)
.Select(tup => Math.Abs(tup.Item1 - tup.Item2) < delta)
.All(b => b);
Assert.IsTrue(areEqual, "Collections differ.");

Unit Test Collection

I have a simple method that returns an array of the letters of the alphabet.
public char[] GetLettersOfTheAlphabet() {
char[] result = new char[26];
int index = 0;
for (int i = 65; i < 91; i++) {
result[index] = Convert.ToChar(i);
index += 1;
}
return result;
}
I tried to unit test the code with
[TestMethod()]
public void GetLettersOfTheAlphabetTest_Pass() {
HomePage.Rules.BrokerAccess.TridionCategories target = new HomePage.Rules.BrokerAccess.TridionCategories();
char[] expected = new char[] { char.Parse("A"),
char.Parse("B"),
char.Parse("C"),
char.Parse("D"),
char.Parse("E"),
char.Parse("F"),
char.Parse("G"),
char.Parse("H"),
char.Parse("I"),
char.Parse("J"),
char.Parse("k"),
char.Parse("L"),
char.Parse("M"),
char.Parse("N"),
char.Parse("O"),
char.Parse("P"),
char.Parse("Q"),
char.Parse("R"),
char.Parse("S"),
char.Parse("T"),
char.Parse("U"),
char.Parse("V"),
char.Parse("W"),
char.Parse("X"),
char.Parse("Y"),
char.Parse("Z")};
char[] actual;
actual = target.GetLettersOfTheAlphabet();
Assert.AreEqual(expected, actual);
}
It seems that it comes down the compare function that the array uses. How do you handle this case?
If you're using .NET 3.5, you can also use SequenceEqual():
[TestMethod()]
public void GetLettersOfTheAlphabetTest_Pass() {
var target = new HomePage.Rules.BrokerAccess.TridionCategories();
var expected = new[] { 'A','B','C', ... };
var actual = target.GetLettersOfTheAlphabet();
Assert.IsTrue(expected.SequenceEqual(actual));
}
CollectionAssert.AreEquivalent(expected, actual) works.
I am not exactly sure how it works but it does work for my needs. I think it checks each item in each item in the expected collection exsits in the actual column, it also checks that they are the same count, but order does not matter.
Just iterate through the array and compare each item. Index of 4 in each array should be identical.
Another way is to check the result array if it contains say 'A', 'G', 'K' or random letters.
Something I have learned from Unit Tests sometimes you have to either copy code or do more work because that is the nature of testing. Basically what works for a unit test might not be acceptable for a production site.
You could also do a test on the size and a few spot checks of values in the array....
Assert.AreEqual(expected.Length, actual.Length)
Assert.AreEqual(expected[0], actual[0])
....
Your K is lowercase in the expected array, but I believe that code generates uppercase characters. If the comparison is case sensitive, it would cause the failure when the two arrays don't match.
First of all:
Assert.AreEqual(expected.Length,actual.Length);
Then:
for(int i = 0; i < actual.Length; i++)
{
//Since you are testing whether the alphabet is correct, then is ok that the characters
//have different case.
Assert.AreEqual(true,actual[i].toString().Equals(expected[i].toString(),StringComparison.OrdinalIgnoreCase));
}

Categories