Is it possible to ignore order of elements in IEnumerable, like in Assert.That( ... , Is.EquivalentTo( ... ));, but using TestCaseData.Returns() in NUnit 3?
If I understand your question correctly, you want to write test cases in NUnit to determine whether two lists are of identical length and contain the same elements, ignoring the order of the elements.
If my interpretation of your question is correct then I have included an example below which should solve your problem:
[TestFixture]
public class MyTests
{
[TestCaseSource(typeof(MyDataClass), nameof(MyDataClass.TestCases))]
public bool ListEqualTest(IEnumerable<int> list1, IEnumerable<int> list2)
{
return list1.Intersect(list2).Count() == list1.Count() && list1.Count == list2.Count;
}
}
public class MyDataClass
{
public static IEnumerable TestCases
{
get
{
var list1 = new List<int> { 1, 2, 3, 4, 5 };
var list2 = new List<int> { 3, 4, 2, 1, 5 };
var list3 = new List<int> { 6, 7, 8, 9, 10 };
var list4 = new List<int> { 6, 7, 8, 11, 12 };
yield return new TestCaseData(list1, list2).Returns(true);
yield return new TestCaseData(list3, list4).Returns(false);
}
}
}
I adapted the example provided in the NUnit documentation, found here.
My solution obviously makes use of the primitive type int when defining the IEnumerable<int> parameters and constructing the List<int> objects but it won't take much effort at all to adapt it for your specific needs.
Hope this helps.
Related
Regarding efficiency, does anyone know if the compiler is clever enough to not create the array containing 1, 3, 5 for each iteration of the loop in the following code?
var foo = new List<int> { 1, 2, 3, 4, 5 };
foo.RemoveAll(i => new[] { 1, 3, 5 }.Contains(i));
I prefer it for readability, but not at the sake of performance.
The answer is no it doesn't optimize out the allocation of the array
Basically, every time the predicate is called, it checks against the compiler generated class and initializes a new array to call the Contains (as you can see here)
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static Predicate<int> <>9__0_0;
internal bool <M>b__0_0(int i)
{
// bam!
int[] obj = new int[3];
RuntimeHelpers.InitializeArray(obj, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
return Enumerable.Contains(obj, i);
}
}
As #Michael Randall already wrote, it looks like it is not possible.
I agree, that your questioned code is nicely readable, having the list in the RemoveAll method. But to have the instance only once, I have three ideas of doing it:
int[] a = null;
foo.RemoveAll(i => (a ?? (a = new[] { 1, 3, 5 })).Contains(i));
This is actually yours, with little un-beatuness of needing an external variable.
foo = foo.Except(new[] { 1, 3, 5 }).ToList();
That's actually pretty nice solution using Linq.
new List<int>{1, 3, 5}.ForEach(x => foo.Remove(x));
new[] {1, 3, 5}.Iterate(x => foo.Remove(x));
This is something I'd do. In neary all of my code I have my Extension method "Iterate" to avoid the need of foreach. And also, i dont want to "toList" everything all the time to make a .ForEach(..)
static class Extensions
{
public static void Iterate<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
{
foreach (var item in source)
{
action.Invoke(item);
}
}
}
Since the compiler is not that smart, we must outsmart him.
var foo = new List<int> { 1, 2, 3, 4, 5 };
var bar = new HashSet<int>() { 1, 3, 5 };
foo.RemoveAll(i => bar.Contains(i));
What are the ways to check if X exists in X,Y,Z in c#?
For eg:
X=5;
I want to check if X's value matches any of the comma separated values..
if(x in (2,5,12,14)
new int[] { 2,5,12,14}.Contains(x);
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
list.Contains(5);
You may use .Contains method. e.g. listItems.Contains(x)
There is no in operator in C#, but you can implement an extension method to make the code more readable.
public static class Ext
{
public static bool In<T>(this T val, params T[] values) where T : struct
{
return values.Contains(val);
}
}
//usage: var exists = num.In(numbers);
Linq.Contains() what you searching for
// Create List with three elements.
var list = new List<string>();
list.Add("cat");
list.Add("dog");
list.Add("moth");
// Search for this element.
if (list.Contains("dog"))
{
Console.WriteLine("dog was found");
}
There are two methods Linq.Contains() method and an extension Linq.Contains<int>
var list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Use extension method.
var stp = new Stopwatch();
stp.Start();
bool a = list.Contains<int>(7);
stp.Stop();
Console.WriteLine("Time in extenstion method {0}", stp.Elapsed);
stp.Restart();
// Use instance method.
bool b = list.Contains(7);
stp.Stop();
Console.WriteLine("Time in normal method {0}", stp.Elapsed);
Performance benchmark : The version specific to List i.e, list.Contains(7); , found on the List type definition, is faster. I tested the same List with the two Contains methods.
For instance, if I had an int[5] array = {1, 2, 3, 4, 5}
and an int check = 5
Is there an easy way to check if (check == any item in array) then do something?
Just use the Contains LINQ method. You'll need to add using System.Linq to access the method.
if(array.Contains(5))
{
//TODO do stuff
}
You can use Enumerable.Contains() method. This method returns true if the source sequence contains an element that has the specified value; otherwise, false.
Determines whether a sequence contains a specified element by using
the default equality comparer.
int[] array = {1, 2, 3, 4, 5};
if(array.Contains(5))
{
Console.WriteLine("Array has an element called 5");
}
Here is a DEMO.
Dont forget to add System.Linq namespace.
NOTE: Positive side of Contains() method, the enumeration is terminated as soon as a matching element is found. If you search the element like;
foreach(var i in array)
{
if(i == 5)
///
}
You have to enumerate all elements in array. I think this is biggest benefit of this method in this situation.
if (array.Contains(check))
{
//code
}
You can say:
array.Contains(check)
You can try this code:
int[] array = { 1, 2, 3, 3, 5 };
int check = 5;
int r = Array.Find<int>(array, (arr => arr == check));
if (r != 0)
{
// then do something.
}
I have created a class that contains a HashSet to keep track of integer numbers from 1-10. I used the Contain method to check if a value is inserted in the HashSet, with a bool. Here is my code:
class BasicIntSet
{
HashSet<int> intTest = new HashSet<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
bool has4 = intTest.Contains(4); // Returns true
bool has11 = intTest.Contains(11); // Returns false
bool result = intTest.IsSupersetOf(new[] { 4, 6, 7 });
}
My problem now is, that I get an error that says "Error 1 A field initializer cannot reference the non-static field, method, or property"
Does anybody know what I'm doing wrong?
All your code is in the class declaration... you're declaring instance fields. You can't make one instance field initializer refer to another (or refer to this in any other way), hence the error.
Fixing it is simple - put your code into a method:
using System;
using System.Collections.Generic;
class BasicIntSet
{
static void Main()
{
HashSet<int> intTest = new HashSet<int> {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Console.WriteLine(intTest.Contains(4)); // True
Console.WriteLine(intTest.Contains(11)); // False
Console.WriteLine(intTest.IsSupersetOf(new[] { 4, 6, 7 })); // True
}
}
Note that your original error has nothing to do with HashSet<T> at all. Here's just about the simplest example I can think of:
class BadFieldInitializers
{
int x = 10;
int y = x;
}
That gives the same error - because again, one field initializer (for y) refers to this implicitly.
Let's say I for example have this class that generates Fibonacci numbers:
public class FibonacciSequence : IEnumerable<ulong>
{
public IEnumerator<ulong> GetEnumerator()
{
var a = 0UL;
var b = 1UL;
var c = a + b;
while (true)
{
yield return c;
c = a + b;
a = b;
b = c;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
I can then write a test that makes sure that the n first numbers in the sequence are correct.
[Test]
public void GetEnumerator_FirstFifteenNumbers_AreCorrect()
{
var sequence = new FibonacciSequence().Take(15).ToArray();
CollectionAssert.AreEqual(sequence, new[] {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610});
}
When I check for coverage however, I will see that the IEnumerable.GetEnumerator() method is untested, and my coverage will be lower than it really needs to be. Fair enough. But how should I test that method?
How do you usually deal with this?
EDIT: Updated based on what Marc said.
Well you could get the coverage up by doing:
// Helper extension method
public static IEnumerable AsWeakEnumerable(this IEnumerable source)
{
foreach (object o in source)
{
yield return o;
}
}
...
[Test]
public void GetEnumerator_FirstFifteenNumbers_AreCorrect()
{
IEnumerable weak = new FibonacciSequence().AsWeakEnumerable();
var sequence = weak.Cast<int>().Take(15).ToArray();
CollectionAssert.AreEqual(sequence,
new[] {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610});
}
Note that weak is declared to be the nongeneric IEnumerable type... which means you need to call Cast on it to cast each returned object to int.
I'm not sure I'd bother though...
You would have to use use IEnumerable (non-generic); I posted a reply using Cast<T>, but that will still cheat (it checked for the desired type as a special case) - you might need something like:
public static int CountUntyped(this IEnumerable source) {
int count = 0;
foreach(object obj in source) { count++; }
return count;
}
IEnumerable<T> source = ...
Assert.AreEqual(typed.Count(), source.CountUntyped());
I wouldn't test it. I would try to filter the method out of the coverage tool. I think coverage should check things I want to have covered and not everything. From other comments you seem to be using TestDriven.Net. I don't know how well that filters but it was possible with NCover. You could try PartCover also.