O MSTest tem um equivalente ao TestCase do NUnit?

107

Acho o TestCaserecurso do NUnit bastante útil como uma maneira rápida de especificar parâmetros de teste sem a necessidade de um método separado para cada teste. Existe algo semelhante no MSTest?

 [TestFixture]  
 public class StringFormatUtilsTest  
 {  
     [TestCase("tttt", "")]  
     [TestCase("", "")]  
     [TestCase("t3a4b5", "345")]  
     [TestCase("3&5*", "35")]  
     [TestCase("123", "123")]  
     public void StripNonNumeric(string before, string expected)  
     {  
         string actual = FormatUtils.StripNonNumeric(before);  
         Assert.AreEqual(expected, actual);  
     }  
 }  
tjjjohnson
fonte
Pergunta semelhante, consulte stackoverflow.com/questions/347535/how-to-rowtest-with-mstest/…
Michael Freidgeim
Por que você não usa o NUnit?
Mike de Klerk,
1
@MikedeKlerk: Nunit é incrivelmente lento se você estiver usando o Entity Framework ... Aparentemente, reflete em todas as suas classes geradas sempre que você executa um teste.
Robert Harvey
De modo geral, o NUnit tem mais recursos do que o MSTest. Se você estiver usando o MSTest apenas para executar seus testes com o VS Test Explorer, poderá fazer o mesmo com o NUnit instalando a extensão do adaptador de teste NUnit via NuGet
Stacked
1
Experimente DataRow(), consulte: blogs.msdn.microsoft.com/devops/2016/06/17/…
Babak

Respostas:

62

A Microsoft anunciou recentemente o "MSTest V2" (consulte o artigo do blog ). Isso permite que você use consistentemente (desktop, UWP, ...) o DataRowatributo -attribute!

 [TestClass]  
 public class StringFormatUtilsTest  
 {  
     [DataTestMethod]  
     [DataRow("tttt", "")]  
     [DataRow("", "")]  
     [DataRow("t3a4b5", "345")]  
     [DataRow("3&5*", "35")]  
     [DataRow("123", "123")]  
     public void StripNonNumeric(string before, string expected)  
     {  
         string actual = FormatUtils.StripNonNumeric(before);  
         Assert.AreEqual(expected, actual);  
     }  
 } 

Novamente, o Test Explorer do Visual Studio Express infelizmente não reconhece esses testes. Mas pelo menos as versões "completas" do VS agora suportam esse recurso!

Para usá-lo, basta instalar os pacotes NuGet MSTest.TestFramework e MSTest.TestAdapter (ambos de pré-lançamento a partir de agora).

Resposta mais antiga:

Se não tiver que ficar com o MSTest e você estiver usando-o apenas para poder executar os testes por meio do Test Explorer porque você só tem uma edição Visual Studio Express, então esta pode ser uma solução para você:

Existe a extensão VsTestAdapter VSIX para ser capaz de executar testes NUnit via Test Explorer. Infelizmente, os usuários do VS Express não podem instalar extensões ... Mas, felizmente, o VsTestAdapter também vem com um pacote NuGet simples !

Portanto, se você for um usuário do VS Express, basta instalar o pacote NuGet do VsTestAdapter e desfrutar da execução de seus testes / casos de teste NUnit através do Test Explorer!


Infelizmente, a afirmação acima não é verdadeira. Embora seja perfeitamente possível instalar o pacote por meio de uma edição Express, é inútil, pois não pode utilizar o Test Explorer. Anteriormente, havia uma observação sobre uma versão mais antiga do TestAdapter, que foi removida da página de descrição do 2.0.0 :

Observe que não funciona com o VS Express

khlr
fonte
4
MSTest "v2" agora é a estrutura padrão ao usar o VS 2017. Agora que ele terá suporte OOTB na versão mais recente, essa informação provavelmente deve ir para o topo da resposta.
Marc L.
34

Eu sei que esta é uma resposta tardia, mas espero que ajude outras pessoas.

Procurei por toda parte uma solução elegante e acabei escrevendo uma para mim. Nós o usamos em mais de 20 projetos com milhares de testes de unidade e centenas de milhares de iterações. Nunca perdeu uma batida.

https://github.com/Thwaitesy/MSTestHacks

1) Instale o pacote NuGet .

2) Herdar sua classe de teste do TestBase

public class UnitTest1 : TestBase
{ }

3) Crie uma propriedade, campo ou método que retorna IEnumerable

[TestClass]
public class UnitTest1 : TestBase
{
    private IEnumerable<int> Stuff
    {
        get
        {
            //This could do anything, get a dynamic list from anywhere....
            return new List<int> { 1, 2, 3 };
        }
    }
}

4) Adicione o atributo MSTest DataSource ao seu método de teste, apontando de volta para o nome IEnumerable acima. Isso precisa ser totalmente qualificado.

[TestMethod]
[DataSource("Namespace.UnitTest1.Stuff")]
public void TestMethod1()
{
    var number = this.TestContext.GetRuntimeDataSourceObject<int>();

    Assert.IsNotNull(number);
}

Resultado final: 3 iterações como o DataSource normal :)

using Microsoft.VisualStudio.TestTools.UnitTesting;
using MSTestHacks;

namespace Namespace
{
    [TestClass]
    public class UnitTest1 : TestBase
    {
        private IEnumerable<int> Stuff
        {
            get
            {
                //This could do anything, get a dynamic list from anywhere....
                return new List<int> { 1, 2, 3 };
            }
        }

        [TestMethod]
        [DataSource("Namespace.UnitTest1.Stuff")]
        public void TestMethod1()
        {
            var number = this.TestContext.GetRuntimeDataSourceObject<int>();

            Assert.IsNotNull(number);
        }
    }
}
Thwaitesy
fonte
Isso também funcionaria com vários parâmetros para cada caso?
Lonefish
Como houve uma alteração na biblioteca subjacente, isso não funciona com o MsTest "v2" . Este é o padrão para VS15 (VS 2017).
Marc L.
3
Sim, se você estiver usando o MSTest V2, há um novo provedor de casos de teste semelhante ao do NUnit. Portanto, não há necessidade dessa solução alternativa em torno de 👏
Thwaitesy
Isso não parece funcionar no VS 2015, o arquivo de configuração do aplicativo não é preenchido dinamicamente e, portanto, as fontes de dados não são encontradas
Reed
13

Eu sei que esta é outra resposta tardia, mas em minha equipe que está presa ao uso da estrutura de teste do MS, desenvolvemos uma técnica que depende apenas de tipos anônimos para manter uma matriz de dados de teste e LINQ para percorrer e testar cada linha. Não requer classes ou estruturas adicionais e tende a ser bastante fácil de ler e entender. Também é muito mais fácil de implementar do que os testes orientados a dados usando arquivos externos ou um banco de dados conectado.

Por exemplo, digamos que você tenha um método de extensão como este:

public static class Extensions
{
    /// <summary>
    /// Get the Qtr with optional offset to add or subtract quarters
    /// </summary>
    public static int GetQuarterNumber(this DateTime parmDate, int offset = 0)
    {
        return (int)Math.Ceiling(parmDate.AddMonths(offset * 3).Month / 3m);
    }
}

Você poderia usar uma matriz de Tipos Anônimos combinados com LINQ para escrever testes como este:

[TestMethod]
public void MonthReturnsProperQuarterWithOffset()
{
    // Arrange
    var values = new[] {
        new { inputDate = new DateTime(2013, 1, 1), offset = 1, expectedQuarter = 2},
        new { inputDate = new DateTime(2013, 1, 1), offset = -1, expectedQuarter = 4},
        new { inputDate = new DateTime(2013, 4, 1), offset = 1, expectedQuarter = 3},
        new { inputDate = new DateTime(2013, 4, 1), offset = -1, expectedQuarter = 1},
        new { inputDate = new DateTime(2013, 7, 1), offset = 1, expectedQuarter = 4},
        new { inputDate = new DateTime(2013, 7, 1), offset = -1, expectedQuarter = 2},
        new { inputDate = new DateTime(2013, 10, 1), offset = 1, expectedQuarter = 1},
        new { inputDate = new DateTime(2013, 10, 1), offset = -1, expectedQuarter = 3}
        // Could add as many rows as you want, or extract to a private method that
        // builds the array of data
    }; 
    values.ToList().ForEach(val => 
    { 
        // Act 
        int actualQuarter = val.inputDate.GetQuarterNumber(val.offset); 
        // Assert 
        Assert.AreEqual(val.expectedQuarter, actualQuarter, 
            "Failed for inputDate={0}, offset={1} and expectedQuarter={2}.", val.inputDate, val.offset, val.expectedQuarter); 
        }); 
    }
}

Ao usar essa técnica, é útil usar uma mensagem formatada que inclui os dados de entrada no Assert para ajudá-lo a identificar qual linha faz com que o teste falhe.

Eu escrevi sobre esta solução com mais informações e detalhes em AgileCoder.net .

Gary.Ray
fonte
4
O maior problema com isso é que, se algum caso falhar na matriz de valores, todo o teste falhará e nenhum outro caso será testado.
ytoledano de
Isso cria casos de teste que podem influenciar uns aos outros.
BartoszKP
@BartoszKP Somente se o sistema em teste tiver efeitos colaterais, caso em que esta provavelmente não é uma técnica ideal.
Gary.Ray de
@ Gary.Ray Além disso, quando o sistema não ter efeitos colaterais ainda . Além disso, quando um teste não passa e outro desenvolvedor tenta consertar isso e perde horas tentando descobrir se a dependência é importante ou não. Isso é apenas algo que você nunca deve fazer, ponto final.
BartoszKP
Bom o bastante. +1
Trey Mack de
7

Khlr deu boas explicações detalhadas e aparentemente essa abordagem começou a funcionar no VS2015 Express for Desktop. Tentei deixar o comentário, mas minha falta de reputação não me permitiu fazê-lo.

Deixe-me copiar a solução aqui:

[TestClass]  
 public class StringFormatUtilsTest  
 {  
     [TestMethod]  
     [DataRow("tttt", "")]  
     [DataRow("", "")]  
     [DataRow("t3a4b5", "345")]  
     [DataRow("3&amp;amp;5*", "35")]  
     [DataRow("123", "123")]  
     public void StripNonNumeric(string before, string expected)  
     {  
         string actual = FormatUtils.StripNonNumeric(before);  
         Assert.AreEqual(expected, actual);  
     }  
 } 

Para usá-lo, basta instalar os pacotes NuGet MSTest.TestFramework e MSTest.TestAdapter .

Um problema é

Erro CS0433 O tipo 'TestClassAttribute' existe em 'Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version = 10.0.0.0 e' Microsoft.VisualStudio.TestPlatform.TestFramework, Version = 14.0.0.0

Portanto, remova Microsoft.VisualStudio.QualityTools.UnitTestFramework das referências do projeto.

Você é muito bem-vindo para editar a resposta original e excluir esta.

Arte
fonte
0

O MSTest tem o atributo DataSource, que permitirá que você alimente uma tabela de banco de dados, csv, xml, etc. Eu usei e funciona bem. Não sei como colocar os dados logo acima como atributos como na sua pergunta, mas é muito fácil configurar as fontes de dados externas e os arquivos podem ser incluídos no projeto. Estava funcionando há uma hora desde o início e não sou um especialista em testes automatizados.

https://msdn.microsoft.com/en-us/library/ms182527.aspx?f=255&MSPPError=-2147217396 tem um tutorial completo baseado na entrada do banco de dados.

http://www.rhyous.com/2015/05/11/row-tests-or-paramerterized-tests-mstest-xml/ tem um tutorial baseado na entrada de arquivo XML.

CindyH
fonte