.net - ¿Utiliza TestInitialize o el constructor de la clase de prueba para preparar cada prueba? ¿y por qué?
unit-testing (8)
Esta pregunta se refiere a las pruebas unitarias en Visual Studio usando MSTest (esto es importante, debido al orden de ejecución de MSTest). Tanto el método marcado [TestInitialize] como el constructor de la clase de prueba se ejecutarán antes de cada método de prueba.
Entonces, la pregunta es, ¿qué tienden a hacer en cada una de estas áreas? ¿Evita realizar ciertas actividades en cualquiera de los dos? ¿Cuál es tu razón: estilo, técnica, superstición?
Aquí hay algunas ventajas que he encontrado con TestInitialize.
- Algunas variables ambientales (por ejemplo, TestContext) no son accesibles hasta después de que se crea una instancia de la clase de prueba.
- Puede requerir implementación con clase derivada marcando un método base TestInitialize abstract.
- Puede anular fácilmente un método TestInitialize base y determinar si se llama a la base impl antes de la impl derivada, después o en absoluto. Por el contrario, si deriva una clase de prueba de una clase de prueba base, en el caso de un constructor sin parámetros, se llamará al ctor base tanto si lo intentó como si no.
- Su definición explícita aclara las intenciones y complementa el método TestCleanup. Podría argumentar que puede crear un destructor para cada constructor, pero no se garantiza que MS Test maneje los destructores como era de esperar.
Depende del escenario Si tiene una clase de prueba, y por algún motivo extraño si necesita crear una instancia de la misma en otra clase de prueba, necesitará usar el constructor.
De lo contrario, pruebe inicializar más ajustes en el concepto. En primer lugar, las mismas razones escritas anteriormente, el segundo MS puede introducir más características en ese atributo y usted las beneficiará, con el constructor se quedará atrapado en él.
El constructor es solo una estructura proporcionada por el lenguaje. Cada marco de prueba parece tener su propio ciclo de vida controlado "inicializar". Probablemente solo tendrá problemas al usar el constructor para mutar sus locals.
MSTest: obtienes una nueva instancia completa de la clase de prueba para cada TestMethod
. Este podría ser el único caso en el que está permitido cambiar las ubicaciones locales en el constructor, el inicializador o el método de prueba y no afectar los otros métodos de prueba.
public class TestsForWhatever
{
public TestsForWhatever()
{
// You get one of these per test method, yay!
}
[TestInitialize]
public void Initialize()
{
// and one of these too!
}
[TestMethod]
public void AssertItDoesSomething() { }
[TestMethod]
public void AssertItDoesSomethingElse() { }
}
MSpec: solo obtienes un Establish
y Because
para todas tus aserciones ( It
). Por lo tanto, no mutes a tus lugareños en tus afirmaciones. Y no dependas de las mutaciones de los locales en contextos base (si los usas).
[Subject(typeof(Whatever))]
public class When_doing_whatever
{
Establish context = () =>
{
// one of these for all your Its
};
Because of = () => _subject.DoWhatever();
It should_do_something;
It should_do_something_else;
}
El objeto que prueba no necesita ser instancied en el método [TestInitialize]. Puede probar el constructor de su objeto en un método de prueba [Prueba].
El objeto en [TestInitialize] puede ser configurar su almacenamiento de persistencia o preparar el valor que el objeto probado utilizará en las pruebas.
Esta pregunta también se formula (más adelante) en ¿Cuál es la diferencia entre usar el constructor en el marco VS Testing framework vs. TestInitialize ()?
FWIW Supongo que por "constructor de clase" te refieres al constructor de instancias (no al constructor estático ).
Creo que la misma pregunta que está preguntando también podría hacerse sobre el constructor estático vs. ClassInitialize ...
La principal ventaja de utilizar TestInitialize () o ClassInitialize () en lugar de la instancia de la clase de prueba o los constructores estáticos es su naturaleza explícita. Comunica claramente que está realizando una configuración antes de sus pruebas. Hacer esto consistentemente debería mejorar el mantenimiento a largo plazo.
Prefiero usar el método [TestInitialize]
para realizar una instanciación del objeto que se está probando y sus parámetros. Solo realizo trabajo en el constructor si es necesario crear una instancia de una clase base de prueba (que generalmente es donde creo o actualizo repositorios, etc.). Esto me ayuda a mantener el código de prueba y el código de prueba separados de forma lógica y física.
Yo digo que use el constructor a menos que necesite TestContext
.
- Si puedes mantener las cosas simples, por qué no. Un constructor es más simple que un atributo mágico.
- Puedes usar
readonly
que es algo muy importante en la inicialización de pruebas en el que quieres preparar cosas para las pruebas que no deberían cambiar (lo ideal es que las cosas que preparases también sean inmutables).