繁体   English   中英

如何测试文化依赖和文化无关的 ToString 方法?

[英]How to test culture-deendent and culture-independent ToString methods?

我必须用换句话说写我的问题。

由于某些原因,我正在开发自己的几何原始结构:点和大小:

public struct Point : IEquatable<Point> {
    public static bool operator ==(Point left, Point right) {
        return left.Equals(right);
    }
    public static bool operator !=(Point left, Point right) {
        return !left.Equals(right);
    }
    public static implicit operator Point(System.Drawing.Point point) {
        return new Point(point.X, point.Y);
    }

    int x;
    int y;

    public int X { get { return x; } set { x = value; } }
    public int Y { get { return y; } set { y = value; } }


    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }


    public bool Equals(Point other) {
        return
            x == other.x &&
            y == other.y;
    }
    public override bool Equals(object obj) {
        if (obj.GetType() != typeof(Point))
            return false;
        return Equals((Point)obj);
    }
    public override int GetHashCode() {
        return x^y;
    }
    public override string ToString() {
        return $"{{X={x.ToString(CultureInfo.CurrentCulture)}, Y={y.ToString(CultureInfo.CurrentCulture)}}}";
    }
    public string ToStringInvariant() {
        return $"{{X={x.ToString(CultureInfo.InvariantCulture)}, Y={y.ToString(CultureInfo.InvariantCulture)}}}";
    }
}

public struct Size : IEquatable<Size> {
    public static bool operator ==(Size size1, Size size2) {
        return size1.Equals(size2);
    }
    public static bool operator !=(Size size1, Size size2) {
        return !size1.Equals(size2);
    }
    public static implicit operator Size(System.Drawing.Size size) {
        return new Size(size.Width, size.Height);
    }

    int width;
    int height;

    public int Width {
        get { return width; }
        set {
            if (value < 0)
                throw new ArgumentException("The Width property value must not be negative.");
            width = value;
        }
    }
    public int Height {
        get { return height; }
        set {
            if (value < 0)
                throw new ArgumentException("The Height property value must not be negative.");
            height = value;
        }
    }

    public Size(int width, int height) {
        if (width < 0 || height < 0)
            throw new ArgumentException("The Width and Height property values must not be negative.");
        this.width = width;
        this.height = height;
    }

    public bool Equals(Size other) {
        return
            width == other.width &&
            height == other.height;
    }
    public override bool Equals(object obj) {
        if (obj.GetType() != typeof(Size))
            return false;
        return Equals((Size)obj);
    }
    public override int GetHashCode() {
        return HashCodeHelper.CalculateGeneric(width, height);
    }
    public override string ToString() {
        return $"{{Width={width.ToString(CultureInfo.CurrentCulture)}, Height={height.ToString(CultureInfo.CurrentCulture)}}}";
    }
    public string ToStringInvariant() {
        return $"{{Width={width.ToString(CultureInfo.InvariantCulture)}, Height={height.ToString(CultureInfo.InvariantCulture)}}}";
    }
}

现在我需要编写测试,特别是我应该测试我的 ToString 和 ToStringInvariant() 方法。

  1. 测试应记录当前行为,以避免功能中出现意外的方法行为更改。
  2. 断言,该 ToString 返回字符串,其中包含当前文化中的数字,但 ToStringInvariant 始终包含具有不变格式数字的字符串。

为此,我需要一些文化,其中整数格式不同于 InvariantCulture 整数格式。

由于 Point 类可以有负数,我可以更改负号表示并编写测试:

[Test]
public void ToStringTest() {
   Point point = new Point(-1, 2);
   var preCulture = Thread.CurrentThread.CurrentCulture;
   try {
        var enCulture = new CultureInfo("en-US");
        enCulture.NumberFormat.NegativeSign = "Minus!";
        Thread.CurrentThread.CurrentCulture = enCulture;
        Assert.That(point.ToString() == "{X=Minus!1, Y=2}");
   }
   finally {
        Thread.CurrentThread.CurrentCulture = preCulture;
   }
}

[Test]
public void ToStringInvariantTest() {
    Point point = new Point(1, 2);
    var preCulture = Thread.CurrentThread.CurrentCulture;
    try {
        var enCulture = new CultureInfo("en-US");
        enCulture.NumberFormat.NegativeSign = "Minus!";
        Thread.CurrentThread.CurrentCulture = enCulture;
        Assert.That(point.ToStringInvariant() == "{X=1, Y=2}");
    }
    finally {
        Thread.CurrentThread.CurrentCulture = preCulture;
    }
}

Size 结构只能有正或零字段,所以我应该更改数字表示。 我尝试使用“prs-AF”文化。 但是 1.ToString("prs-AF") 仍然是“1”。 如何测试 Size 结构的 ToString 和 ToStringInvariant 方法?

旧文本:


我有原语:Point 和 Size 类。 我以这种方式覆盖 ToString 方法:

public override string ToString() {
    return $"{{X={x.ToString(CultureInfo.CurrentCulture)}, Y={y.ToString(CultureInfo.CurrentCulture)}}}";
}

我也有一个

    public string ToStringInvariant() {
        return $"{{X={x.ToString(CultureInfo.InvariantCulture)}, Y={y.ToString(CultureInfo.InvariantCulture)}}}";
    }

我需要对这种方法进行测试。 对于 Point 类,我可以在 CultureInfo 实例中设置 NegativeSign:

    [Test]
    public void ToStringTest() {
        Point point = new Point(-1, 2);
        var preCulture = Thread.CurrentThread.CurrentCulture;
        try {
            var enCulture = new CultureInfo("en-US");
            enCulture.NumberFormat.NegativeSign = "Minus!";
            Thread.CurrentThread.CurrentCulture = enCulture;
            Assert.That(point.ToString() == "{X=Minus!1, Y=2}");
        }
        finally {
            Thread.CurrentThread.CurrentCulture = preCulture;
        }
    }

但是对于 Size 类我不能这样做,因为 Width 和 Height 不能为负数,所以我需要创建一个 CultureInfo 实例,其中正数不包含 {1,2,3,4,5,6, 7,8,9,0}。

如果没有这样的文化,我只是不需要这个 Size 类的测试。

目前还不清楚问题是什么,甚至这里正在测试什么。 ToString仅添加{X=..., Y=...}模板,其余的被委托给字段类型(例如decimaldouble )。 Point.ToString()Size.ToString()单元测试中没有点单元测试decimal.ToString()

基类库中的本地化敏感类无论如何都接受CultureInfo参数,它们不依赖于当前环境文化。 在很多情况下,当前的文化不一定是我们真正想要的文化,例如在 Web 应用程序中,或者当我们想要在特定语言环境中读取或写入文件时。

最好有一个其他人委托给的ToString(CultureInfo)方法。 这将简化测试并减少重复。 使用String.Format将进一步减少代码减少出错的机会:

public string ToString(CultureInfo culture)
{
    return String.Format(culture,"{X={0}, Y={1}}",X,Y);
}

public override string ToString()=>ToString(CultureInfo.CurrentCulture);

//Really, this should be ToStringUS();
public string ToStringInvariant()=>ToString(CultureInfo.InvariantCulture);

格式字符串可以有不同的部分来为负数或零指定不同的格式,例如:

"{X={0:#;(#)}, Y={1:#;(#)}}"

或者

"{X={0:#;Minus!#;**Zero**}, Y={1:#;Minus!#;**Zero**}}"

Rant : InvariantCulture本质上是美国文化。 数字可以,但在格式化日期时会成为一个严重的问题。 它不是标准的 YYYY-MM-DD 格式,而是生成美国风格的日期。

无论方法如何实现,唯一需要单元测试的部分是该方法的输出,而不是decimal本身的格式。

[TestCase("en-US","{X=-1.5, Y=2.6}")
[TestCase("en-UK","{X=-1,5, Y=2,6}")
public void ToString_Is_Locale_Aware(string culture,string expected)
{
    var ci=CultureInfo.GetCulture(culture);
    var point=new Point(-1.5,2.6);
    
    var actual=point.ToString(ci);

    Assert.AreEqual(expected,actual);
}

[TestCase("en-US","{X=-1.5, Y=2.6}")
[TestCase("en-UK","{X=-1,5, Y=2,6}")
public void ToStringBase_Is_Locale_Aware(string culture,string expected)
{
    var point=new Point(-1.5,2.6);
    var ci=CultureInfo.GetCulture(culture);    
    var preCulture = Thread.CurrentThread.CurrentCulture;
    try {
        Thread.CurrentThread.CurrentCulture = ci;

        var actual=point.ToString();

        Assert.AreEqual(expected,actual);
    }
    finally {
        Thread.CurrentThread.CurrentCulture = preCulture;
    }
}

测试ToStringInvariant只需要证明字符串不会改变

[TestCase("en-US")
[TestCase("en-UK")
[TestCase("de-DE")
public void ToStringInvariant_Is_Locale_Unaware(string culture)
{
    var point=new Point(-1.5,2.6);    
    var ci=CultureInfo.GetCulture(culture);
    var preCulture = Thread.CurrentThread.CurrentCulture;
    try {
        Thread.CurrentThread.CurrentCulture = ci;

        var actual=point.ToStringInvariant();

        Assert.AreEqual("{X=-1.5, Y=2.6}",actual);
    }
    finally {
        Thread.CurrentThread.CurrentCulture = preCulture;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM