新手如何组织和组织单元测试? [英] Newbie; how to structure and organize unit tests?

查看:115
本文介绍了新手如何组织和组织单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是单元测试的新手,刚刚创建了我的第一组测试.我对此有一个疑问是测试的顺序或组织.我有一个VS2008项目,并为使用2种方法的类编写了一些测试.

使用VS工具时,它将创建具有2个测试方法的1个测试类.由于类中的每个方法都需要测试多个内容,因此我在相应的testmethod中为该方法创建了所有测试.当涉及到异常时,令我震惊的是< ExpectedException>. 属性应用于TestMethod级别,指示每个测试方法只能处理1个异常.

所以现在更大的问题是;如何组织测试代码?

  • 每个类一个TestClass,每个方法一个TestMethod?这与< ExpectedException>有什么关系?属性?
  • 每个测试都应该有自己的TestMethod吗?这将导致大量的测试方法,如何管理这些方法?
  • 我也有多个项目(每个项目都有很多类);每个项目1个测试项目,每个课程1个测试课程?

如何使事情保持整洁,简单但又井井有条?在这方面的任何指导将不胜感激.有一些最佳做法吗?

 

这是我为这两种方法创建的代码,我个人认为它很杂乱(我对消息进行编号以更好地了解失败的原因),所以我希望在这里寻求更好的解决方案;

  '''<summary>
  '''A test for encString2Bytes
  '''</summary>
  <TestMethod()> _
  <Description("Testing encoder from a string to a byte array")> _
  <Owner("Tieske")> _
  Public Sub encString2BytesTest()
    Dim data As String = String.Empty
    Dim expected(255) As Byte
    Dim actual() As Byte
    ' create expected array
    For n As UInt16 = 0 To 255
      expected(n) = CByte(n)
      data = data & Chr(n)
      Assert.AreEqual(Asc(Chr(n)), CInt(n), "1 - ASC and CHR not equal")
    Next
    ' convert to byte array
    actual = Utility.encString2Bytes(data)
    ' verify byte by byte
    For n As UInt16 = 0 To 255
      Assert.AreEqual(actual(n), expected(n), "2 - Character " & n & " in the array is not equal to expected character")
    Next
    ' convert returned array back to a string and compare to original string
    Assert.AreEqual(data, Utility.encBytes2String(actual), "3 - Converting string to bytes and bytes to string resulted in a different string")

    ' encode a empty string
    ReDim actual(-1)
    CollectionAssert.AreEqual(actual, Utility.encString2Bytes(""), "4 - Empty string does not get encoded as zero-length array")

    ' encode string nothing/null
    Assert.IsNull(Utility.encString2Bytes(Nothing), "5 - Encoding string NULL does not return NULL")
  End Sub

  '''<summary>
  '''A test for encBytes2String
  '''</summary>
  <TestMethod()> _
  <Description("Testing decoder from a byte array to a string")> _
  <Owner("Tieske")> _
  Public Sub encBytes2StringTest()
    Dim dummy As Byte()
    Dim data(255) As Byte
    Dim ByteCount As Integer = 0
    Dim expected As String = ""
    Dim actual As String = ""

    ' create expected array
    For n As UInt16 = 0 To 255
      data(n) = CByte(n)
      expected = expected & Chr(n)
      Assert.AreEqual(Asc(Chr(n)), CInt(n), "1 - ASC and CHR not equal")
    Next

    ' test decode byte array with all (0-255) byte present
    actual = Utility.encBytes2String(data)
    Assert.AreEqual(expected, actual, "2 - String converted from byte array doesn't ,match expected value")

    ' test zero length array
    ReDim dummy(-1)
    Assert.AreEqual("", Utility.encBytes2String(dummy), "3 - Zero length array didn't result in an empty string")

    ' test NULL
    Assert.IsNull(Utility.encBytes2String(Nothing), "4 - NULL did not return NULL as a result")

    ' proper ByteCount, correct length returned?
    Assert.AreEqual(10, Utility.encBytes2String(data, 10).Length, "5 - Number of characters returned doesn't match requested ByteCount")

    ' improper Bytecount; -10, out of range exception
    Try
      Utility.encBytes2String(data, -10)
      Assert.Fail("6 - ArgumentOutOfRange exception not thrown")
    Catch ex As Exception
      Assert.IsInstanceOfType(ex, GetType(ArgumentOutOfRangeException), "6 - exception was not ArgumentOutOfRange")
    End Try

    ' improper ByteCount; longer then data array, out of range exception
    Try
      Utility.encBytes2String(data, data.Length + 10)
      Assert.Fail("7 - ArgumentOutOfRange exception not thrown")
    Catch ex As Exception
      Assert.IsInstanceOfType(ex, GetType(ArgumentOutOfRangeException), "7 - exception was not ArgumentOutOfRange")
    End Try

  End Sub

解决方案

嗨Tieske,

您的问题涉及很多领域,让我尽力帮助您.有多种可行的选择,从每个类具有一个测试类到多个类.这取决于您的课程的复杂性.一般来说我会继续1 1,但还取决于下一个问题:要在测试中测试什么(TestMethod).

每次测试仅测试一项特定项目/功能.这真的很重要,因为您只希望测试失败有1个原因.如果您的班级没有凝聚力,这将在您的测试班级中创建大量的测试清单(查找SOLID).现在,如果您发现 您需要编写大量测试来测试一个类,因此您很可能在该类中做得太多.将这些片段重构为帮助程序类,并对其进行测试.

关于此主题,有一些很好的读物.我建议您从 SOLID电子书开始(易于阅读,只有40页左右).然后继续 xUnit测试模式,并阅读前100页.您可以将本书的其余部分用作各种可用测试模式的参考.如果您使用的是旧版系统,我将介绍Micheal Feathers出色的< 在职的 带有遗留代码".

亲切的问候,
汤姆·德·科宁

 


Hi,

I'm new to unit testing and just created my first set of tests. A question I have regarding this is the ordering of the test, or the organization. I have a VS2008 project, and written some tests for a class with 2 methods.

When using the VS tools it creates 1 test class with 2 testmethods. As each method in my class has multiple things to test, I created all tests for that method in the corresponding testmethod. When getting to the exceptions, It struck me that the <ExpectedException> attribute is applied at the TestMethod level, indicating that can only handle 1 exception per testmethod.

So the bigger question now is; how to organize the test code?

  • One TestClass per class, and one TestMethod per method? how does this relate to the <ExpectedException> attribute?
  • Should each test have its own TestMethod? this would result in a huge amount of testmethods, how to manage these?
  • I also have multiple projects (and each project has many classes); 1 test project per project, 1 test class per class?

How to keep things neat and simple, yet well organized? any guidance in this area would be appreciated. Are there some best practices?

 

Here's the code I created for the 2 methods, personally I think its messy (I numbered the messages to getter a better idea of what failed), so I'm hoping for some better solution here;

  '''<summary>
  '''A test for encString2Bytes
  '''</summary>
  <TestMethod()> _
  <Description("Testing encoder from a string to a byte array")> _
  <Owner("Tieske")> _
  Public Sub encString2BytesTest()
    Dim data As String = String.Empty
    Dim expected(255) As Byte
    Dim actual() As Byte
    ' create expected array
    For n As UInt16 = 0 To 255
      expected(n) = CByte(n)
      data = data & Chr(n)
      Assert.AreEqual(Asc(Chr(n)), CInt(n), "1 - ASC and CHR not equal")
    Next
    ' convert to byte array
    actual = Utility.encString2Bytes(data)
    ' verify byte by byte
    For n As UInt16 = 0 To 255
      Assert.AreEqual(actual(n), expected(n), "2 - Character " & n & " in the array is not equal to expected character")
    Next
    ' convert returned array back to a string and compare to original string
    Assert.AreEqual(data, Utility.encBytes2String(actual), "3 - Converting string to bytes and bytes to string resulted in a different string")

    ' encode a empty string
    ReDim actual(-1)
    CollectionAssert.AreEqual(actual, Utility.encString2Bytes(""), "4 - Empty string does not get encoded as zero-length array")

    ' encode string nothing/null
    Assert.IsNull(Utility.encString2Bytes(Nothing), "5 - Encoding string NULL does not return NULL")
  End Sub

  '''<summary>
  '''A test for encBytes2String
  '''</summary>
  <TestMethod()> _
  <Description("Testing decoder from a byte array to a string")> _
  <Owner("Tieske")> _
  Public Sub encBytes2StringTest()
    Dim dummy As Byte()
    Dim data(255) As Byte
    Dim ByteCount As Integer = 0
    Dim expected As String = ""
    Dim actual As String = ""

    ' create expected array
    For n As UInt16 = 0 To 255
      data(n) = CByte(n)
      expected = expected & Chr(n)
      Assert.AreEqual(Asc(Chr(n)), CInt(n), "1 - ASC and CHR not equal")
    Next

    ' test decode byte array with all (0-255) byte present
    actual = Utility.encBytes2String(data)
    Assert.AreEqual(expected, actual, "2 - String converted from byte array doesn't ,match expected value")

    ' test zero length array
    ReDim dummy(-1)
    Assert.AreEqual("", Utility.encBytes2String(dummy), "3 - Zero length array didn't result in an empty string")

    ' test NULL
    Assert.IsNull(Utility.encBytes2String(Nothing), "4 - NULL did not return NULL as a result")

    ' proper ByteCount, correct length returned?
    Assert.AreEqual(10, Utility.encBytes2String(data, 10).Length, "5 - Number of characters returned doesn't match requested ByteCount")

    ' improper Bytecount; -10, out of range exception
    Try
      Utility.encBytes2String(data, -10)
      Assert.Fail("6 - ArgumentOutOfRange exception not thrown")
    Catch ex As Exception
      Assert.IsInstanceOfType(ex, GetType(ArgumentOutOfRangeException), "6 - exception was not ArgumentOutOfRange")
    End Try

    ' improper ByteCount; longer then data array, out of range exception
    Try
      Utility.encBytes2String(data, data.Length + 10)
      Assert.Fail("7 - ArgumentOutOfRange exception not thrown")
    Catch ex As Exception
      Assert.IsInstanceOfType(ex, GetType(ArgumentOutOfRangeException), "7 - exception was not ArgumentOutOfRange")
    End Try

  End Sub

解决方案

Hi Tieske,

Your question covers quite a bit of ground, let me try to help you as good as possible. There are multiple options feasible, from having one test class per class to many. This depends on the complexity of your class. Generally speaking I would go for 1 on 1, but also depends on the next issue: what to test in tests (the TestMethod).

You only test for one specific item / feature per test. This is really important as you only want the test to fail for 1 reason. This will create a huge list of tests in your test class if your class is not cohesive (look up SOLID). Now, if you find out that you need write a lot of tests to bring one class under test, you are most likely doing too much in that class. Refactor the pieces out to helper classes and bring those under test.

There are several very good reads available on this topic. I suggest you start with the SOLID ebook (easy read, only 40 pages or so). Then move on to xUnit test patterns and read the first 100 pages. The rest of the book you can use as reference to the various test patterns available. If you are dealing with a legacy system, I would have a look at Micheal Feathers excellent "Working with legacy code". 

Kind regards,
Tom de Koning

 


这篇关于新手如何组织和组织单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆