El nombramiento básico de una prueba consta de tres partes principales: [UnitOfWork_StateUnderTest_ExpectedBehavior] Una unidad de trabajo es un caso de uso en el sistema que comienza con un método público y termina con uno de los tres tipos de resultados: un valor / excepción de retorno, un cambio de estado en el sistema que cambia su comportamiento o una llamada a un Tercero (cuando usamos mocks). por lo tanto, una unidad de trabajo puede ser pequeña como un método, o tan grande como una clase, o incluso múltiples clases. siempre y cuando todo se ejecute en la memoria, y está totalmente bajo nuestro control.
Examples:
Public void Sum_NegativeNumberAs1stParam_ExceptionThrown()
Public void Sum_NegativeNumberAs2ndParam_ExceptionThrown ()
Public void Sum_simpleValues_Calculated ()
Razones:
El nombre de la prueba debe expresar un requisito específico
El nombre de su prueba de unidad debe expresar un requisito específico. Este requisito debe derivarse de algún modo de un requisito comercial o de un requisito técnico. En cualquier caso, ese requisito se ha dividido en partes suficientemente pequeñas, cada una de las cuales representa un caso de prueba. Si su prueba no representa un requisito, ¿por qué la escribe? ¿Por qué es ese código incluso allí?
Además, los desarrolladores que están en un rol están felices de dar nombres sin sentido o numerados a su prueba para que puedan continuar con lo que están haciendo. Esto conduce a una pendiente estrecha donde rápidamente nadie tiene el tiempo o la energía para arreglar los nombres de las pruebas. Además, la mayoría de los desarrolladores no se preocupan demasiado por escribir buenos mensajes de afirmación en sus pruebas. Un buen mensaje de afirmación (que aparece si la prueba falla) es para comprender qué salió mal. Asumir que los mensajes de aseveración son buenos es uno de los lugares clave donde la mayoría de los desarrolladores de pruebas unitarias se quedan cortos, lo único que queda para salvarnos es el nombre de la prueba. Si tanto el nombre de la prueba como los mensajes de error no son lo suficientemente expresivos, el desarrollador de mantenimiento deficiente (a menudo el mismo que desarrolló las pruebas) se pregunta qué pensaba este bromista. Mirando un código base de años con pruebas unitarias.
El nombre de la prueba debe incluir la entrada o estado esperado y el resultado esperado para esa entrada o estado
Para expresar claramente el requisito específico, debe pensar en dos cosas que debe expresar: los valores de entrada / estado actual durante el cual se realiza la prueba y el resultado esperado de ese estado.
Ejemplo:
Dado este método:Example:
Public int Sum(params int[] values)
You have a requirement that numbers larger than 1000 that are passed in should not be considered for calculation (that is a number bigger than 1000 is equal to zero).
What about this name: Sum_NumberBiggerThan1000
That is only half way there. As a reader of the test I can only assume that some input in your test is bigger than 1000, but I do not understand what the requirement being tested is.
How about this name: Sum_NumberIsIgnored
Still not good enough. While it does tell me the expected result, it does not tell me under which circumstances it needs to be ignored. I would have to go into the test code and read through it to find out what the expected input is.
How about this name: Sum_NumberIgnoredIfBiggerThan1000
That s much better. I can tell just by looking at the test name what It means if the test fails. I don t need to look at the code, and I can tell exactly what requirement this test tries to solve.
Test name should be presented as a statement or fact of life that expresses workflows and outputs
Unit tests are just as much about documentation as they are about testing functionality. You should always assume that someone else is going to read your tests in a year, and that they should not have a hard time understanding your intent.
Test names which are written as short declarative statements are much more expressive that names which are machine readable that is they only make sense if you have an understanding of a hidden code language to dissect their meaning.
People might first complain that the name of the test method appears way too long for them, but in the end it s more about readability. Longer test names do not imply longer or less optimized code, and even if they did, we are not looking to optimize test code performance. If anything, test code should always be optimized for readability.
Here s an example of a bad an d good test name
Public void SumNegativeNumber2()
And here s a better way to express your intent
Public void Sum_ExceptionThrownOnNegativeNumberAs2ndParam ()
Test Name should only begin with Test if it is required by the testing framework or if it eases development and maintenance of the unit tests in some way.
Since most tests today reside in a specific class or module that is logically defined as a test container (fixture), there are only a handful of reasons why you would want to prefix you test methods with the word Test :
- Your unit testing framework requires this
- You have coding standards in place and they include this
- You want to make it easier to navigate to the methods using Intellisense or some other search mechanism.
Test name should include name of tested method or class
You usually have at least a number of tests for each method you are testing, and you are usually testing a number of methods in one test fixture (since you usually have a test fixture per class tested). This leads to the requirement that your test should also reflect the name of the method begin tested, not only the requirements from it.
For example:
[MethodName_StateUnderTest_ExpectedBehavior]
Public void Sum_NegativeNumberAs1stParam_ExceptionThrown()
Public void Sum_NegativeNumberAs2ndParam_ExceptionThrown ()
Public void Sum_simpleValues_Calculated ()
Public void Parse_OnEmptyString_ExceptionThrown()
Public void Parse_SingleToken_ReturnsEqualToeknValue ()
Naming Variables in a test:
Variable names should express the expected input and state
It s easy to name variables going into a method with generic names, but with unit tests you have to be twice as careful to name them as what they represent, i.e. BAD_DATA or EMPTY_ARRAY or NON_INITIALIZED_PERSON
You do not need to name them with a CONST casing , but the name does have to represent the intent of the test author.
A good way to check if your names are good enough is to look at the ASSERT at the end of the test method. If the ASSERT line is expressing what your requirement is, or comes close, you re probably there.
For example:
Assert.AreEqual(-1, val)
Vs.
Assert.AreEqual(BAD_INITIALIZATION_CODE, ReturnCode, Method shold have returned a bad initialization code )