我试图完成编程练习但是一次测试失败了。我做错了什么?
任务是:
编写管理机器人出厂设置的程序。
当机器人从工厂车间出来时,他们没有名字。
第一次启动它们时,会生成一个随机名称,例如 RX837或BC811。
每隔一段时间我们就需要将机器人重置为工厂 设置,这意味着他们的名字被擦除。下次你 问,它有一个新名字。
该程序的测试如下所示,失败的测试是 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));
}
}
我的代码如下所示:
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 = "";
}
}
答案 0 :(得分:3)
使Names
静态传递所有测试:
private static List<string> Names = new List<string>();
Static关键字表示正在类级别创建成员,而不是对象。
在您的情况下所有机器人将共享指向单个名称列表的链接。删除static关键字将导致Names
列表创建每 Robot对象。如果你想跟踪Robots构造函数的调用次数,你应该有一个共享的名字列表,它在所有Robot对象中共享。
您的测试失败,因为当创建第二个对象时,它有一个 new 空名称列表,第一个Robot类对此一无所知。因此,在您的情况下,Names.Any(...)
将始终返回false。
要阅读更多详细信息,请考虑上面的msdn链接。
答案 1 :(得分:2)
错误并不明显。使用从当前系统时间创建的随机种子初始化Random
类。与CPU时钟频率相比,产生系统时间的手表速度缓慢。因此,如果random
被调用为快两次,new Random()
很可能会使用相同的种子初始化两次。
解决方案:将随机声明为静态并仅初始化一次。
public class Robot
{
private static Random random = new Random();
...
}
现在random
只会创建一次,无论您创建多少个机器人。