Unit Test Collection - c#

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));
}

Related

FsCheck: How to generate test data that depends on other test data?

FsCheck has some neat default Arbitrary types to generate test data. However what if one of my test dates depends on another?
For instance, consider the property of string.Substring() that a resulting substring can never be longer than the input string:
[Fact]
public void SubstringIsNeverLongerThanInputString()
{
Prop.ForAll(
Arb.Default.NonEmptyString(),
Arb.Default.PositiveInt(),
(input, length) => input.Get.Substring(0, length.Get).Length <= input.Get.Length
).QuickCheckThrowOnFailure();
}
Although the implementation of Substring certainly is correct, this property fails, because eventually a PositiveInt will be generated that is longer than the genereated NonEmptyString resulting in an exception.
Shrunk: NonEmptyString "a" PositiveInt 2 with exception: System.ArgumentOutOfRangeException: Index and length must refer to a location within the string.
I could guard the comparison with an if (input.Length < length) return true; but that way I end up with lots of test runs were the property isn't even checked.
How do I tell FsCheck to only generate PositiveInts that don't exceed the input string? I presume I have to use the Gen<T> class, but it's interface is just hella confusing to me... I tried the following but still got PositiveInts exceeding the string:
var inputs = Arb.Default.NonEmptyString();
// I have no idea what I'm doing here...
var lengths = inputs.Generator.Select(s => s.Get.Length).ToArbitrary();
Prop.ForAll(
inputs,
lengths,
(input, length) => input.Get.Substring(0, length).Length <= input.Get.Length
).QuickCheckThrowOnFailure();
You can create generators which depend on values generated from another using SelectMany. This also allows you to use the LINQ query syntax e.g.
var gen = from s in Arb.Generate<NonEmptyString>()
from i in Gen.Choose(0, s.Get.Length - 1)
select Tuple.Create(s, i);
var p = Prop.ForAll(Arb.From(gen), t =>
{
var s = t.Item1.Get;
var len = t.Item2;
return s.Substring(0, len).Length <= s.Length;
});
Check.Quick(p);

How to reverse string in C# [duplicate]

I didn't get the problem - I was trying to do a simple action:
for(i = x.Length-1, j = 0 ; i >= 0 ; i--, j++)
{
backx[j] = x[i];
}
Both are declared:
String x;
String backx;
What is the problem ? It says the error in the title...
If there is a problem - is there another way to do that?
The result (As the name 'backx' hints) is that backx will contain the string X backwards.
P.S. x is not empty - it contains a substring from another string.
Strings are immutable: you can retrieve the character at a certain position, but you cannot change the character to a new one directly.
Instead you'll have to build a new string with the change. There are several ways to do this, but StringBuilder does the job in a similar fashion to what you already have:
StringBuilder sb = new StringBuilder(backx);
sb[j] = x[i];
backx = sb.ToString();
EDIT: If you take a look at the string public facing API, you'll see this indexer:
public char this[int index] { get; }
This shows that you can "get" a value, but because no "set" is available, you cannot assign values to that indexer.
EDITx2: If you're looking for a way to reverse a string, there are a few different ways, but here's one example with an explanation as to how it works: http://www.dotnetperls.com/reverse-string
String is immutable in .NET - this is why you get the error.
You can get a reverse string with LINQ:
string x = "abcd";
string backx = new string(x.Reverse().ToArray());
Console.WriteLine(backx); // output: "dcba"
String are immuatable. You have convert to Char Array and then you would be able to modify.
Or you can use StringBuilder.
for example
char[] wordArray = word.ToCharArray();
In C# strings are immutable. You cannot "set" Xth character to whatever you want. If yo uwant to construct a new string, or be able to "edit" a string, use i.e. StringBuilder class.
Strings are immutable in C#. You can read more about it here: http://msdn.microsoft.com/en-us/library/362314fe.aspx
Both the variables you have are string while you are treating them as if they were arrays (well, they are). Of course it is a valid statement to access characters from a string through this mechanism, you cannot really assign it that way.
Since you are trying to reverse a string, do take a look at this post. It has lot of information.
public static string ReverseName( string theName)
{
string revName = string.Empty;
foreach (char a in theName)
{
revName = a + revName;
}
return revName;
}
This is simple and does not involve arrays directly.
The code below simply swaps the index of each char in the string which enables you to only have to iterate half way through the original string which is pretty efficient if you're dealing with a lot of characters. The result is the original string reversed. I tested this with a string consisting of 100 characters and it executed in 0.0000021 seconds.
private string ReverseString(string testString)
{
int j = testString.Length - 1;
char[] charArray = new char[testString.Length];
for (int i = 0; i <= j; i++)
{
if (i != j)
{
charArray[i] = testString[j];
charArray[j] = testString[i];
}
j--;
}
return new string(charArray);
}
In case you need to replace e.g. index 2 in string use this (it is ugly, but working and is easily maintainbable)
V1 - you know what you want to put their. Here you saying in pseudocode string[2] = 'R';
row3String.Replace(row3String[2], 'R');
V2 - you need to put their char R or char Y. Here string[2] = 'R' if was 'Y' or if was not stay 'Y' (this one line if needs some form of else)
row3String.Replace(row3String[2], row3String[2].Equals('Y') ? 'R' : 'Y');

Remove item from a simple array one time

How to remove item from a simple array once? For example, a char array contains these letters:
a,b,d,a
I would like to remove the letter "a" one time, then the result would be:
a,b,d
Removing an item from an array is not really possible. The size of an array is immutable once allocated. There is no way to remove an element per say. You can overwrite / clear an element but the size of the array won't change.
If you want to actually remove an element and change the size of the collection then you should use List<char> instead of char[]. Then you can use the RemoveAt API
List<char> list = ...;
list.RemoveAt(3);
If your goal is to just skip the first 'a', then remove the second, you could use something like:
int first = Array.IndexOf(theArray, 'a');
if (first != -1)
{
int second = Array.IndexOf(theArray, 'a', first+1);
if (second != -1)
{
theArray = theArray.Take(second - 1).Concat(theArray.Skip(second+1)).ToArray();
}
}
If you just need to remove any of the 'a' characters (since you specified that the order is not relevant), you could use:
int index = Array.IndexOf(theArray, 'a');
if (index != -1)
{
theArray = theArray.Take(index - 1).Concat(theArray.Skip(index+1)).ToArray();
}
Note that these don't actually remove the item from the array - they create a new array with that element missing from the newly created array. Since arrays are not designed to change in total length once created, this is typically the best alternative.
If you will be doing this frequently, you may want to use a collection type that does allow simple removal of elements. Switching from an array to a List<char>, for example, makes removal far simpler, as List<T> supports simple APIs such as use List<T>.Remove directly.
You can use linq by trying the following
var someArray= new string[3];
someArray[0] = "a";
someArray[1] = "b";
someArray[2] = "c";
someArray= someArray.Where(sa => !sa.Equals("a")).ToArray();
Please note: This method is not removing the element from the array but that it is creating a new array that is excluding the element. This may have an effect on performance.
You might consider using a list or collection.
static void Main(string[] args)
{
char[] arr = "aababde".ToArray();
arr = RemoveCharacter(arr, 'a');
arr = RemoveCharacter(arr, 'b');
arr = RemoveCharacter(arr, 'd');
arr = RemoveCharacter(arr, 'z');
arr = RemoveCharacter(arr, 'a');
//result is 'a' 'b' 'e'
}
static char[] RemoveCharacter(char[] array, char c)
{
List<char> list = array.ToList();
list.Remove(c);
return list.ToArray();
}

How to test function returns IEnumerable<Integer>

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

How to search a string in String array

I need to search a string in the string array. I dont want to use any for looping in it
string [] arr = {"One","Two","Three"};
string theString = "One"
I need to check whether theString variable is present in arr.
Well, something is going to have to look, and looping is more efficient than recursion (since tail-end recursion isn't fully implemented)... so if you just don't want to loop yourself, then either of:
bool has = arr.Contains(var); // .NET 3.5
or
bool has = Array.IndexOf(arr, var) >= 0;
For info: avoid names like var - this is a keyword in C# 3.0.
Every method, mentioned earlier does looping either internally or externally, so it is not really important how to implement it. Here another example of finding all references of target string
string [] arr = {"One","Two","Three"};
var target = "One";
var results = Array.FindAll(arr, s => s.Equals(target));
Does it have to be a string[] ? A List<String> would give you what you need.
List<String> testing = new List<String>();
testing.Add("One");
testing.Add("Two");
testing.Add("Three");
testing.Add("Mouse");
bool inList = testing.Contains("Mouse");
bool exists = arr.Contains("One");
I think it is better to use Array.Exists than Array.FindAll.
Its pretty simple. I always use this code to search string from a string array
string[] stringArray = { "text1", "text2", "text3", "text4" };
string value = "text3";
int pos = Array.IndexOf(stringArray, value);
if (pos > -1)
{
return true;
}
else
{
return false;
}
If the array is sorted, you can use BinarySearch. This is a O(log n) operation, so it is faster as looping. If you need to apply multiple searches and speed is a concern, you could sort it (or a copy) before using it.
Each class implementing IList has a method Contains(Object value). And so does System.Array.
Why the prohibition "I don't want to use any looping"? That's the most obvious solution. When given the chance to be obvious, take it!
Note that calls like arr.Contains(...) are still going to loop, it just won't be you who has written the loop.
Have you considered an alternate representation that's more amenable to searching?
A good Set implementation would perform well. (HashSet, TreeSet or the local equivalent).
If you can be sure that arr is sorted, you could use binary search (which would need to recurse or loop, but not as often as a straight linear search).
You can use Find method of Array type. From .NET 3.5 and higher.
public static T Find<T>(
T[] array,
Predicate<T> match
)
Here is some examples:
// we search an array of strings for a name containing the letter “a”:
static void Main()
{
string[] names = { "Rodney", "Jack", "Jill" };
string match = Array.Find (names, ContainsA);
Console.WriteLine (match); // Jack
}
static bool ContainsA (string name) { return name.Contains ("a"); }
Here’s the same code shortened with an anonymous method:
string[] names = { "Rodney", "Jack", "Jill" };
string match = Array.Find (names, delegate (string name)
{ return name.Contains ("a"); } ); // Jack
A lambda expression shortens it further:
string[] names = { "Rodney", "Jack", "Jill" };
string match = Array.Find (names, n => n.Contains ("a")); // Jack
At first shot, I could come up with something like this (but it's pseudo code and assuming you cannot use any .NET built-in libaries). Might require a bit of tweaking and re-thinking, but should be good enough for a head-start, maybe?
int findString(String var, String[] stringArray, int currentIndex, int stringMaxIndex)
{
if currentIndex > stringMaxIndex
return (-stringMaxIndex-1);
else if var==arr[currentIndex] //or use any string comparison op or function
return 0;
else
return findString(var, stringArray, currentIndex++, stringMaxIndex) + 1 ;
}
//calling code
int index = findString(var, arr, 0, getMaxIndex(arr));
if index == -1 printOnScreen("Not found");
else printOnScreen("Found on index: " + index);
In C#, if you can use an ArrayList, you can use the Contains method, which returns a boolean:
if MyArrayList.Contains("One")
You can check the element existence by
arr.Any(x => x == "One")
it is old one ,but this is the way i do it ,
enter code herevar result = Array.Find(names, element => element == "One");
I'm surprised that no one suggested using Array.IndexOf Method.
Indeed, Array.IndexOf has two advantages :
It allows searching if an element is included into an array,
It gets at the same time the index into the array.
int stringIndex = Array.IndexOf(arr, theString);
if (stringIndex >= 0)
{
// theString has been found
}
Inline version :
if (Array.IndexOf(arr, theString) >= 0)
{
// theString has been found
}
Using Contains()
string [] SomeArray = {"One","Two","Three"};
bool IsExist = SomeArray.Contains("One");
Console.WriteLine("Is string exist: "+ IsExist);
Using Find()
string [] SomeArray = {"One","Two","Three"};
var result = Array.Find(SomeArray, element => element == "One");
Console.WriteLine("Required string is: "+ result);
Another simple & traditional way, very useful for beginners to build logic.
string [] SomeArray = {"One","Two","Three"};
foreach (string value in SomeArray) {
if (value == "One") {
Console.WriteLine("Required string is: "+ value);
}
}

Categories