As a continuation to my recent rant about the differences between programmers and developers and how programmers love to code and … well, everything it is mentioned in that post, I felt like sharing a little bit of fun I had with this stackoverflow question.
Since it had already been answered and actually there was a little debate going on about the pros and cons of the accepted answer I was about to close it and look for something else when I decided to have a little bit of fun and make the solution generic.
Not like it was difficult, after a couple of minutes I had this:
public class PropertyValidator { public bool Validate<T, TResult>(IEnumerable<T> list, Func<T, TResult> expression) { return list.Select(expression).Distinct().Count() <= 1; } }
But the fun didn’t end there, since this was not needed in what I was working on I had to demonstrate that it worked by other means, what could those means possibly be? You guessed it, unit tests!
[TestClass] public class SameValueInPropertyValidatorTests { private PropertyValidator _validator; [TestInitialize] public void Initialize() { _validator = new PropertyValidator(); } [TestMethod] public void ReturnsTrueIfListIsEmpty() { var list = new List<string>(); Func<string, string> expression = x => x; var result = _validator.Validate(list, expression); Assert.IsTrue(result); } [TestMethod] public void ReturnsTrueWhenValuesAreSameForStrings() { var list = new List<string> {"1", "1", "1", "1", "1", "1"}; Func<string, string> expression = x => x; var result = _validator.Validate(list, expression); Assert.IsTrue(result); } [TestMethod] public void ReturnsFalseWhenValuesAreNotSameForStrings() { var list = new List<string> { "1", "1", "2", "1", "1", "1" }; Func<string, string> expression = x => x; var result = _validator.Validate(list, expression); Assert.IsFalse(result); } [TestMethod] public void ReturnsTrueWhenValuesAreSameForKeyValuePair() { var list = new List<KeyValuePair<string, int>> { new KeyValuePair<string, int>("any1", 1), new KeyValuePair<string, int>("any2", 1), new KeyValuePair<string, int>("any3", 1), new KeyValuePair<string, int>("any4", 1), }; Func<KeyValuePair<string, int>, int> expression = x => x.Value; var result = _validator.Validate(list, expression); Assert.IsTrue(result); } [TestMethod] public void ReturnsFalseWhenValuesAreNotSameForKeyValuePair() { var list = new List<KeyValuePair<string, int>> { new KeyValuePair<string, int>("any1", 1), new KeyValuePair<string, int>("any2", 1), new KeyValuePair<string, int>("any3", 456), new KeyValuePair<string, int>("any4", 1), }; Func<KeyValuePair<string, int>, int> expression = x => x.Value; var result = _validator.Validate(list, expression); Assert.IsFalse(result); } [TestMethod] public void ReturnsTrueWhenValuesAreSameForEnumProperty() { var list = new List<Car> { new Car {Color = Colors.Red}, new Car {Color = Colors.Red}, new Car {Color = Colors.Red}, new Car {Color = Colors.Red}, }; Func<Car, Colors> expression = x => x.Color; var result = _validator.Validate(list, expression); Assert.IsTrue(result); } [TestMethod] public void ReturnsFalseWhenValuesAreNotSameForEnumProperty() { var list = new List<Car> { new Car {Color = Colors.Red}, new Car {Color = Colors.Red}, new Car {Color = Colors.Black}, new Car {Color = Colors.Red}, }; Func<Car, Colors> expression = x => x.Color; var result = _validator.Validate(list, expression); Assert.IsFalse(result); } }
And since we were on a roll, why not remove the duplication by creating generic methods to assert the results:
[TestClass] public class SameValueInPropertyValidatorTests { private PropertyValidator _validator; [TestInitialize] public void Initialize() { _validator = new PropertyValidator(); } [TestMethod] public void ReturnsTrueIfListIsEmpty() { var list = new List<string>(); Func<string, string> expression = x => x; AssertIsTrue(list, expression); } [TestMethod] public void ReturnsTrueWhenValuesAreSameForStrings() { var list = new List<string> { "1", "1", "1", "1", "1", "1" }; Func<string, string> expression = x => x; AssertIsTrue(list, expression); } [TestMethod] public void ReturnsFalseWhenValuesAreNotSameForStrings() { var list = new List<string> { "1", "1", "2", "1", "1", "1" }; Func<string, string> expression = x => x; AssertIsFalse(list, expression); } [TestMethod] public void ReturnsTrueWhenValuesAreSameForKeyValuePair() { var list = new List<KeyValuePair<string, int>> { new KeyValuePair<string, int>("any1", 1), new KeyValuePair<string, int>("any2", 1), new KeyValuePair<string, int>("any3", 1), new KeyValuePair<string, int>("any4", 1), }; Func<KeyValuePair<string, int>, int> expression = x => x.Value; AssertIsTrue(list, expression); } [TestMethod] public void ReturnsFalseWhenValuesAreNotSameForKeyValuePair() { var list = new List<KeyValuePair<string, int>> { new KeyValuePair<string, int>("any1", 1), new KeyValuePair<string, int>("any2", 1), new KeyValuePair<string, int>("any3", 456), new KeyValuePair<string, int>("any4", 1), }; Func<KeyValuePair<string, int>, int> expression = x => x.Value; AssertIsFalse(list, expression); } [TestMethod] public void ReturnsTrueWhenValuesAreSameForEnumProperty() { var list = new List<Car> { new Car {Color = Colors.Red}, new Car {Color = Colors.Red}, new Car {Color = Colors.Red}, new Car {Color = Colors.Red}, }; Func<Car, Colors> expression = x => x.Color; AssertIsTrue(list, expression); } [TestMethod] public void ReturnsFalseWhenValuesAreNotSameForEnumProperty() { var list = new List<Car> { new Car {Color = Colors.Red}, new Car {Color = Colors.Red}, new Car {Color = Colors.Black}, new Car {Color = Colors.Red}, }; Func<Car, Colors> expression = x => x.Color; AssertIsFalse(list, expression); } private void AssertIsTrue<T, TResult>(IEnumerable<T> list, Func<T, TResult> expression) { var result = _validator.Validate(list, expression); Assert.IsTrue(result); } private void AssertIsFalse<T, TResult>(IEnumerable<T> list, Func<T, TResult> expression) { var result = _validator.Validate(list, expression); Assert.IsFalse(result); } }
Not exactly a break through discovery or even a coding kata but still it was a cute exercise for me to kill some time.
Would you like to share your favorite exercises or your sources of inspiration for coding research? I’d love to hear about them.