I'm trying to complete a programming exercise but one test fails. What have i done wrong?
The task is:
Write a program that manages robot factory settings.
When robots come off the factory floor, they have no name.
The first time you boot them up, a random name is generated, such as
RX837 or BC811.
Every once in a while we need to reset a robot to its factory
settings, which means that their name gets wiped. The next time you
ask, it gets a new name.
The tests for the program looks like this and the one that fails is the Different_robots_have_different_names:
public class RobotNameTest
{
private Robot robot;
[SetUp]
public void Setup()
{
robot = new Robot();
}
[Test]
public void Robot_has_a_name()
{
StringAssert.IsMatch(#"[A-Z]{2}\d{3}", robot.Name);
}
[Test]
public void Name_is_the_same_each_time()
{
Assert.That(robot.Name, Is.EqualTo(robot.Name));
}
[Test]
public void Different_robots_have_different_names()
{
var robot2 = new Robot();
Assert.That(robot.Name, Is.Not.EqualTo(robot2.Name));
}
[Test]
public void Can_reset_the_name()
{
var originalName = robot.Name;
robot.Reset();
Assert.That(robot.Name, Is.Not.EqualTo(originalName));
}
}
My code looks like this:
public class Robot
{
private List<string> Names = new List<string>();
private string name { get; set; }
public string Name { get { return this.name; } }
public Robot()
{
CreateName();
}
private void CreateName()
{
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var random = new Random();
StringBuilder sb = new StringBuilder();
sb.Append(
new string(
Enumerable.Repeat(chars, 3)
.Select(x => x[random.Next(x.Length)]).ToArray()
)
);
sb.Append(random.Next(100, 999));
if(Names.Any(word => word.Equals(sb.ToString())))
{
CreateName();
}
else
{
name = sb.ToString();
Names.Add(sb.ToString());
}
}
public void Reset()
{
this.name = "";
}
}
Making Names static passes all the tests:
private static List<string> Names = new List<string>();
Static keyword means that the member is being created on the class level, not the object.
In your case all Robots would share a link to a single list of Names. Removing the static keyword would result in Names list being create per Robot object. If you want to track how many times Robots constructor has been called, you should probably have a shared list of names, which is shared across all Robot object.
Your tests fails because when second object is created, it has a new empty Names list, which first Robot class knows nothing about. So in your case Names.Any(...) would always return false.
To read in more details consider msdn link above.
The mistake is not obvious. The Random class gets initialized with a random seed created from the current system time. The watch yielding the system time ticks slowly compared to the CPU clock frequency. Therefore it is well possible that random gets initialized twice with the same seed if new Random() is called to fast twice.
Solution: Declare random as static and initialize it only once.
public class Robot
{
private static Random random = new Random();
...
}
Now random is created only once no matter how many robots you create.
Related
Let's say its the 15th and my function runs, if that function is called again on the 15th it will not run. But if the date is the 16th and the function is called, then it is allowed to run.
How could I achieve this?
P.S. Code below is in visual basic however C# is fine for an answer
Private Sub CreateLogger()
Logger = New CustomLogger(Sub(value, Type)
Dim tempFileLogPath = IO.Path.Combine("C:\temp", $"FileAttributer_{Today:yyyyMMdd}.txt")
Dim consoleLogger = New ConsoleLogger()
Dim textFileLogger = New TextFileLogger(tempFileLogPath)
Dim compositeLogger = New CompositeLogger(consoleLogger, textFileLogger)
value = $"{DateTime.Now:dd/MM/yyyy HH:mm:ss} - {value}"
compositeLogger.Write(value, Type)
End Sub)
End Sub
I suppose this has to do with the file, so in the end you do not end up with multiple files per day.
You could do a check on the file to see if it was created before or not.
I would store the last called time in a variable, and update it every time you call it. It doesn't need to include the time of day, just the date. Every time you call the function, check if the last called time is equal to the current date, and if it is return/throw error to stop the rest of the function.
You have to save the last run time somewhere and compare the day every time.
This is a very simple example how to do it:
using System;
using System.Threading;
public class Program
{
private static DateTime lastRunTime;
public static void Main()
{
for(int i=0; i < 10; i++) {
DoSomething();
Thread.Sleep(1000);
}
}
private static void DoSomething()
{
if (DateTime.Now.Day != lastRunTime.Day) {
lastRunTime = DateTime.Now;
Console.WriteLine($"Run: {lastRunTime}");
}
}
}
But I guess, Radu Hatos is right. You should better explain, why do you want you function to behave so.
You could create a simple class like the one below to manage your calls.
(It is just a very simple example)
public abstract class ExecutionManager
{
protected string ActionKey { get; }
public ExecutionManager(string actionKey)
{
ActionKey = actionKey;
}
protected abstract DateTime GetLastExecution();
protected abstract void SetLastExecution(DateTime dateTime);
public void OncePerDay(Action action)
{
if (GetLastExecution().Date != DateTime.Now.Date)
{
SetLastExecution(DateTime.Now);
action();
}
}
}
You would then implement this abstract class according to you needs: if you run the app on a single machine (console app for instance), you can implement a registry version or a file version to store the lats call dates / times.
If you run seveal instances on several servers, you will have to store the information in a database for instance, or a shared folder (there light be complex mutual exclision issues to manage here)
You will find below a very simple implementation with a file storage for the single computer scenario:
public class LADExecutionManager : ExecutionManager
{
private static string FilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "MyApplicationName");
public LADExecutionManager(string actionKey) : base(actionKey)
{
if (!File.Exists(FilePath))
Directory.CreateDirectory(FilePath);
}
protected string FileName => Path.Combine(FilePath, $"{ActionKey}.txt");
protected override DateTime GetLastExecution()
{
try
{
var sDate = File.ReadAllLines(FileName).First();
return DateTime.Parse(sDate);
}
catch
{
return DateTime.MinValue;
}
}
protected override void SetLastExecution(DateTime dateTime)
{
File.WriteAllLines(FileName, new string[] { dateTime.ToLongDateString() });
}
}
To use these classes, you would code something like
internal class Program
{
private static void Main(string[] args)
{
var em = new LADExecutionManager("MyActionKeyName");
em.OncePerDay(() => MyAction());
}
public static void MyAction()
{
// Action...
Debug.WriteLine("Executing Action");
}
}
You just have to set an action key name in the constructor for each method (You could use reflection to get the method name but I think it is off topic here)
I have a public static method that uses an object of Random class to generate an integer. The integer is then made the index of a List. I want to test the logic of the method while having control over what a random object's Next method returns.
public class RandomGenerator
{
// a static method which produces a random selection from a List
public static string GetRandomListMember(List<string> anyStringList)
{
Random rand = new Random();
int randomInt = rand.Next(anyStringList.Count);
return anyStringList[randomInt];
}
}
From my MSTest file:
[TestClass]
public class RandomGeneratorSpec
{
[TestMethod]
public void GetRandomListMember_ListOfStrings()
{
List<string> strings = new List<string> { "red", "yellow", "green" };
Mock<Random> mockRandom = new Mock<Random>();
mockRandom.Setup(rand => rand.Next(strings.Count)).Returns(() => 2); // 2!
string result = RandomGenerator.GetRandomListMember(strings);
Assert.AreEqual("green", result);
}
}
I want mockRandom.Next to return 2 every time it runs in this test. Obviously, this isn't the way to do it. I've been searching through examples, but they all seem to utilize methods on the object and with instance methods instead of static methods.
How do I control what a built-in method returns while unit testing a method that utilizes it?
Consider refactoring to allow a more maintainable design
public class RandomGenerator {
private readonly Random random;
public RandomGenerator(Random random = default(Random)) {
this.random = random ?? new Random();
}
public string GetRandomListMember(List<string> anyStringList) {
int randomInt = random.Next(anyStringList.Count);
return anyStringList[randomInt];
}
}
Which allows more flexibility with using and testing the subject class
[TestClass]
public class RandomGeneratorSpec {
[TestMethod]
public void GetRandomListMember_ListOfStrings() {
//Arrange
List<string> strings = new List<string> { "red", "yellow", "green" };
string expected = "green";
Mock<Random> mockRandom = new Mock<Random>();
mockRandom.Setup(rand => rand.Next(strings.Count)).Returns(() => 2); // 2!
var subject = new RandomGenerator(mockRandom.Object);
//Act
string actual = subject.GetRandomListMember(strings);
//Assert
Assert.AreEqual(expected, actual);
}
}
Ideally if this generator is to be used as a service, it should have its own abstraction
public interface IRandomGenerator {
string GetRandomListMember(List<string> anyStringList);
}
public class RandomGenerator : IRandomGenerator {
//...omitted for brevity
}
so that it can be injected explicitly where needed and not be used statically as a tightly coupled dependency that can be considered a code smell.
You could create your own Random class locally with whatever methods you need to redefine from the System.Random class.
class Program
{
static void Main(string[] args)
{
var rand = new Random();
int next = rand.Next(); // uses my local Random class.
}
}
class Random
{
public int Next() => 2;
}
An example of my suggestion in the comment:
[TestClass]
public class RandomGeneratorSpec
{
[TestMethod]
public void GetRandomListMember_ListOfStrings()
{
List<string> strings = new List<string> { "red", "yellow", "green" };
string result = RandomGenerator.GetRandomListMember(strings);
Assert.IsTrue(strings.Contains(result));
}
}
using System;
public class Program
{
public static void Main()
{
IRunnable runnable = new Runnable();
for(int i=0;i<10;i++)
{
RunIt(runnable);
}
}
public static void RunIt(IRunnable runnable)
{
var context = new Context();
context.Id = runnable.RunAsync((id,result)=>{
//context.Id will always match "id" here?
context.Result = result; // can I assume here that this is the same context?
});
}
public interface IRunnable
{
int RunAsync(Action<string,string> successHandler);
}
public class Runnable : IRunnable
{
private Random _random = new Random();
public string RunAsync(Action<string,string> successHandler)
{
var guid = Guid.NewGuid().ToString();
Task.Run(()=>
{
Thread.Sleep(_random.Next(0,1000));
successHandler(guid, "result")
});
return guid;
}
}
public class Context
{
public string Id {get;set;}
public string Result{get;set;}
}
}
In this example I'm running function RunIt in a loop. RunIt starts a process asynchronously and assign anonymous handler when it's done. In the same function we have a context variable which will be captured by anonymous lambda. My question is simple - can I assume that captured context will always match the result? My concern here is that I'm running it 10 times which means successHandler will be called 10 times in unordered manner. Is there a separate version of anonymous function per each context?
Long story short - will context.Id always match successHandler "id" in anonymous function?
I know this question was downvoted but I'll answer it anyway. The answer is yes, Context variable will be captured separately per each iteration.
I have implemented a basic binary heap. I wanted to see just how well it performed so I wrote a quick manual 'profiler':
public class MProfile : IDisposable
{
private static Dictionary<string, ProfilerEntry> _funcs = new Dictionary<string, ProfilerEntry>();
private Stopwatch _stopwatch;
private ProfilerEntry _entry;
public MProfile(string funcName)
{
if (!_funcs.ContainsKey(funcName))
{
_funcs.Add(funcName, new ProfilerEntry(funcName));
}
_entry = _funcs[funcName];
_stopwatch = Stopwatch.StartNew();
}
public void Dispose()
{
_stopwatch.Stop();
_entry.Record(_stopwatch.Elapsed.TotalMilliseconds);
}
}
The idea was to wrap it around functions calls with using and it would record the time taken. The ProfileEntry class is just a number of calls and total time taken. By storing them against the name, I can add them up.
Now, if I wrap it around my entire test:
Random random = new Random();
int count = 20000;
using (MProfile profile = new MProfile("HeapTest"))
{
PriorityHeap<PretendPathNode> heap = new PriorityHeap<PretendPathNode>(count);
for (int i = 0; i < count; i++)
{
int next = random.Next(-1000, 1000);
heap.Insert(new PretendPathNode(next));
}
while (heap.Count() > 0)
{
heap.Pop();
}
}
It will tell me that this took: 40.6682ms
However, if I add more profiler around the Insert and Pop calls, i.e:
using (MProfile profile2 = new MProfile("Insert"))
{
heap.Insert(new PretendPathNode(next));
}
using (MProfile profile3 = new MProfile("Pop"))
{
heap.Pop();
}
The total time taken is now: 452ms, with 107ms being from Insert and 131ms being from Pop (note: I've run these tests in huge loops and taken an average). I gather that my extra 'profiling' code will obviously have an impact, but how is it bloating the Insert and Pop times to above the original execution time? I thought they way I'd done the disposable meant that -only- the inner execution time would get recorded, which would still be exactly the same. The extra creating disposable, looking up the func in the dictionary and disposing happens -outside- of the Insert/Pop calls.
Is it to do with things like JIT and compile/run time optimizations? Has throwing in that disposable effectively ruined it? I thought maybe it was GC related but I tried a different profiler (static manual calls to start/stop) that had 0 garbage and it's the same...
Edit: I get the same times using this slightly more confusing code, which caches the MProfile objects and Stopwatch objects, so there is less creation/GC.
public class MProfile : IDisposable
{
private static Dictionary<string, ProfilerEntry> _funcs = new Dictionary<string, ProfilerEntry>();
private static Dictionary<string, Stopwatch> _stopwatches = new Dictionary<string, Stopwatch>();
private static Dictionary<string, MProfile> _profiles = new Dictionary<string, MProfile>();
private ProfilerEntry _entry;
private string _name;
public MProfile(string funcName)
{
_name = funcName;
_entry = new ProfilerEntry(funcName);
_funcs.Add(funcName, _entry);
}
public static MProfile GetProfiler(string funcName)
{
if (!_profiles.ContainsKey(funcName))
{
_profiles.Add(funcName, new MProfile(funcName));
_stopwatches.Add(funcName, new Stopwatch());
}
_stopwatches[funcName].Restart();
return _profiles[funcName];
}
public void Dispose()
{
_stopwatches[_name].Stop();
_entry.Record(_stopwatches[_name].Elapsed.TotalMilliseconds);
}
}
And calling it via:
using (profile2 = MProfile.GetProfiler("Insert"))
Consider the following code:
class Program
{
static Program() {
Program.program1.Value = 5;
}
static List<Program> values = new List<Program>();
int value;
int Value
{
get { return value; }
set {
this.value = value;
Program.values.Add(this);
}
}
static Program program1 = new Program { value = 1 };
static Program program2 = new Program { value = 2 };
static Program program3 = new Program { value = 3 };
static void Main(string[] args)
{
if (Program.values.Count == 0) Console.WriteLine("Empty");
foreach (var value in Program.values)
Console.WriteLine(value.Value);
Console.ReadKey();
}
}
It prints only the number 5, and if removed the code in the static constructor, it prints "Empty".
Is there a way to force static fields to be initialized even whether not used yet?
I need to have a static property named Values with returns all instances of the referred type.
I tried some variations of this code and some works for some types but doesn't for others.
EDIT: THE SAMPLE ABOVE IS BROKEN, TRY THIS ONE:
class Subclass<T> {
static Subclass()
{
Values = new List<Subclass<T>>();
}
public Subclass()
{
if (!Values.Any(i => i.Value.Equals(this.Value)))
{
Values.Add(this);
}
}
public T Value { get; set; }
public static List<Subclass<T>> Values { get; private set; }
}
class Superclass : Subclass<int>
{
public static Superclass SuperclassA1 = new Superclass { Value = 1 };
public static Superclass SuperclassA2 = new Superclass { Value = 2 };
public static Superclass SuperclassA3 = new Superclass { Value = 3 };
public static Superclass SuperclassA4 = new Superclass { Value = 4 };
}
class Program
{
static void Main(string[] args)
{
//Console.WriteLine(Superclass.SuperclassA1); //UNCOMMENT THIS LINE AND IT WORKS
foreach (var value in Superclass.Values)
{
Console.WriteLine(value.Value);
}
Console.ReadKey();
}
}
There is actually a way to force the initialization of the properties in this case. The change requires adding a type parameter to the base class to represent the future subclass of the base class that will contain the fields to be initialized. Then we can use the RuntimeHelpers.RunClassConstructor to ensure that the sub class static fields are initialized.
The following will yield the results that you are looking for:
class Subclass<TSubclass, T>
{
static Subclass()
{
Values = new List<Subclass<TSubclass, T>>();
// This line is where the magic happens
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(TSubclass).TypeHandle);
}
public Subclass()
{
if (!Values.Any(i => i.Value.Equals(this.Value)))
{
Values.Add(this);
}
}
public T Value { get; set; }
public static List<Subclass<TSubclass, T>> Values { get; private set; }
}
class Superclass : Subclass<Superclass, int>
{
public static Superclass SuperclassA1 = new Superclass { Value = 1 };
public static Superclass SuperclassA2 = new Superclass { Value = 2 };
public static Superclass SuperclassA3 = new Superclass { Value = 3 };
public static Superclass SuperclassA4 = new Superclass { Value = 4 };
}
public class Program
{
public static void Main()
{
foreach (var value in Superclass.Values)
{
Console.WriteLine(value.Value);
}
Console.ReadKey();
}
}
What is happening is, the call to RuntimeHelpers.RunClassConstructor(typeof(TSubclass).TypeHandle) forces the static constructor of TSubclass to execute if it has not already run. This ensures that the static fields have initialized first as per this line from https://msdn.microsoft.com/en-us/library/aa645612(VS.71).aspx :
If a class contains any static fields with initializers, those initializers are executed in textual order immediately prior to executing the static constructor.
Here is a dotnetfiddle demonstrating it working:
https://dotnetfiddle.net/MfXzFd
The answer to your question is 'well, yes'. But one of the two ways of "forcing" it is what you're already doing.
The relevant section in the language spec is Static constructors, and specifically:
The static constructor for a class executes at most once in a given
application domain. The execution of a static constructor is triggered
by the first of the following events to occur within an application
domain:
An instance of the class is created.
Any of the static members of the class are referenced.
If a class contains the Main method (Section 3.1) in which execution
begins, the static constructor for that class executes before the Main
method is called. If a class contains any static fields with
initializers, those initializers are executed in textual order
immediately prior to executing the static constructor.
But you're never setting the property -- instead you're setting the backing field directly, so not going through your logic to add to the static list when creating program1, program2 and program3.
i.e. you need to change:
static Program program1 = new Program { value = 1 };
static Program program2 = new Program { value = 2 };
static Program program3 = new Program { value = 3 };
to:
static Program program1 = new Program { Value = 1 };
static Program program2 = new Program { Value = 2 };
static Program program3 = new Program { Value = 3 };
Actually looks you misspelled 'value' -> 'Value'
So:
static Program program1 = new Program { Value = 1 };
static Program program2 = new Program { Value = 2 };
static Program program3 = new Program { Value = 3 };
pretty prints more lines
The second sample doesn't work simply because Value is a static member of Subclass.
C# syntax allows Superclass.Values, but eventually the compiled method call will be to the Subclass.Values getter. So the type Superclass is never actually touched. Superclass.SuperclassA1 on the other hand does touch the type and triggers the static initialization.
This is why C# doesn't really have implicit static initialization and you need composition frameworks like MEF and Unity.