Como executar um método de teste com vários parâmetros no MSTest?


140

O NUnit possui um recurso chamado Valores, como abaixo:

[Test]
public void MyTest(
    [Values(1,2,3)] int x,
    [Values("A","B")] string s)
{
    // ...
}

Isso significa que o método de teste será executado 6 vezes:

MyTest(1, "A")
MyTest(1, "B")
MyTest(2, "A")
MyTest(2, "B")
MyTest(3, "A")
MyTest(3, "B")

Estamos usando o MSTest agora, existe algum equivalente para isso, para que eu possa executar o mesmo teste com vários parâmetros?

[TestMethod]
public void Mytest()
{
    // ...
}

Você pode usar o MSTestHacks, conforme descrito na resposta stackoverflow.com/a/19536942/52277 .
Michael Freidgeim


@MichaelFreidgeim Esta pergunta tem respostas melhores do que o seu alvo sugerido
Rob

1
@ Rob: IMHO, a resposta mais adequada -MSTestHacks - Como RowTest com MSTest? está faltando nesta pergunta.
Michael Freidgeim

@MichaelFreidgeim Talvez, embora pareça que a funcionalidade já exista há 3 anos e meio ( stackoverflow.com/questions/9021881/… )
Rob

Respostas:


46

Infelizmente, ele não é suportado no MSTest. Aparentemente, existe um modelo de extensibilidade e você pode implementá-lo . Outra opção seria usar testes orientados a dados .

Minha opinião pessoal seria apenas ficar com o NUnit ...

Edição: a partir do Visual Studio 2012, atualização 1, o MSTest tem um recurso semelhante. Veja a resposta de @ McAden abaixo.


Estamos usando o Selenium, que gera o código NUnit, então trocamos para usar o NUnit :) #
The Light

4
Descobri que algo semelhante agora é possível na Atualização 1 do Visual Studio 2012, apenas a FYI para consideração futura de qualquer pessoa que esteja olhando para esta resposta.
21312 McAden

@McAden você tem um link com uma explicação?
jeroenh

6
Dei uma resposta abaixo com um exemplo e um link para o meu blog. Ele menciona os atributos necessários e também a propriedade "DisplayName" no atributo que distingue os casos no Test Explorer. Também foi mencionado no anúncio de outubro do CTP (que agora tem o lançamento oficial) blogs.msdn.com/b/visualstudioalm/archive/2012/10/26/… Adicionei as informações a essa pergunta do SO porque passou bastante tempo procurando por ele. Espero que isso poupe a alguém algum tempo.
22468 McAden

167

EDIT 4 : Parece que isso foi concluído no MSTest V2 17 de junho de 2016: https://blogs.msdn.microsoft.com/visualstudioalm/2016/06/06/17/taking-the-mstest-framework-forward-with-mstest- v2 /

Resposta original :

Há cerca de uma semana, no Visual Studio 2012 Update 1, algo semelhante agora é possível:

[DataTestMethod]
[DataRow(12,3,4)]
[DataRow(12,2,6)]
[DataRow(12,4,3)]
public void DivideTest(int n, int d, int q)
{
  Assert.AreEqual( q, n / d );
}

EDIT : Parece que isso só está disponível no projeto de teste de unidade do WinRT / Metro . Vadio

EDIT 2 : A seguir, os metadados encontrados usando "Ir para a definição" no Visual Studio:

#region Assembly Microsoft.VisualStudio.TestPlatform.UnitTestFramework.dll, v11.0.0.0
// C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0\ExtensionSDKs\MSTestFramework\11.0\References\CommonConfiguration\neutral\Microsoft.VisualStudio.TestPlatform.UnitTestFramework.dll
#endregion

using System;

namespace Microsoft.VisualStudio.TestPlatform.UnitTestFramework
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class DataTestMethodAttribute : TestMethodAttribute
    {
        public DataTestMethodAttribute();

        public override TestResult[] Execute(ITestMethod testMethod);
    }
}

EDIT 3 : Esse problema foi levantado nos fóruns do UserVoice do Visual Studio. Estados da última atualização:

INÍCIO · Equipe do Visual Studio ADMIN A equipe do Visual Studio (Equipe do produto, Microsoft Visual Studio) respondeu · 25 de abril de 2016 Obrigado pelo feedback. Começamos a trabalhar nisso.

Pratap Lakshman Visual Studio

https://visualstudio.uservoice.com/forums/330519-team-services/suggestions/3865310-allow-use-of-datatestmethod-datarow-in-all-unit


4
Windows Phone é agora suportado também, com o Visual Studio 2012 Update 2 (atualmente, CTP 4)
Pedro Lamas

8
Eu tenho a atualização 1, mas DataTestMethod e DataRow não são reconhecidos. Em qual biblioteca esses atributos estão?
DevDave

3
Existe alguma fonte oficial sobre o DataTestMethod? Em que namespace está, em qual assembly?
Igor Lankin

2
Descobri que o UnitTestFramework.dll estava instalado no meu computador e, depois de referenciá-lo manualmente, consegui escrever um método usando o atributo [DataTestMethod] com linhas de dados, mas não consigo obter o Test Explorer no Visual Studio 2012.3 para encontrar o método.
21413 Josh DeLong

5
Eu fui para o caminho do arquivo "C: \ Arquivos de programas (x86) \ Microsoft SDKs \ Windows \ v8.0 \ ExtensionSDKs \ MSTestFramework \ 11.0 \ References \ CommonConfiguration \ neutral \ Microsoft.VisualStudio.TestPlatform.UnitTestFramework.dll" no meu computador e o arquivo estava lá. Então, eu o referenciei no meu projeto básico de teste de unidade. Abrir a dll no JustDecompile mostra que a biblioteca possui apenas referências ao mscorlib, System e System.Core. Não é um projeto da Windows Store.
Josh DeLong

34

Esse recurso está em pré-lançamento agora e funciona com o VS 2015.

Por exemplo:

[TestClass]
public class UnitTest1
{
    [DataTestMethod]
    [DataRow(1, 2, 2)]
    [DataRow(2, 3, 5)]
    [DataRow(3, 5, 8)]
    public void AdditionTest(int a, int b, int result)
    {
        Assert.AreEqual(result, a + b);
    }
}

Essa é a resposta correta. Observe que não é necessário dizer [DataTestMethod] para usar o [DataRow] ( stackoverflow.com/a/59162403/2540235 )
mattavatar

11

Como ninguém mencionou - não exatamente o mesmo que os atributos de NUnit Value(ou TestCase), mas o MSTest tem DataSourceatributo, o que permite que você faça coisas semelhantes. Você pode conectá-lo ao banco de dados ou arquivo XML - não tão direto quanto o recurso do NUnit, mas faz o trabalho.


7

MSTest tem um atributo poderoso chamado DataSource . Com isso, você pode executar um teste controlado por dados conforme solicitado. Você pode ter seus dados de teste em XML, CSV ou em um banco de dados. Aqui estão alguns links que o guiarão

http://visualstudiomagazine.com/articles/2009/09/15/unit-testing-with-vsts2008-part-3.aspx http://msdn.microsoft.com/en-us/library/ms182527.aspx
http: //msdn.microsoft.com/en-us/library/ms243192.aspx

Espero que isso ajude você.


6

É muito simples de implementar - você deve usar TestContextproperty e TestPropertyAttribute.

Exemplo

public TestContext TestContext { get; set; }
private List<string> GetProperties()
{
    return TestContext.Properties
        .Cast<KeyValuePair<string, object>>()
        .Where(_ => _.Key.StartsWith("par"))
        .Select(_ => _.Value as string)
        .ToList();
}

//usage
[TestMethod]
[TestProperty("par1", "http://getbootstrap.com/components/")]
[TestProperty("par2", "http://www.wsj.com/europe")]
public void SomeTest()
{
    var pars = GetProperties();
    //...
}

EDITAR:

Eu preparei alguns métodos de extensão para simplificar o acesso à TestContextpropriedade e agir como se tivéssemos vários casos de teste. Veja o exemplo com o processamento de propriedades simples de teste aqui:

[TestMethod]
[TestProperty("fileName1", @".\test_file1")]
[TestProperty("fileName2", @".\test_file2")]
[TestProperty("fileName3", @".\test_file3")]
public void TestMethod3()
{
    TestContext.GetMany<string>("fileName").ForEach(fileName =>
    {
        //Arrange
        var f = new FileInfo(fileName);

        //Act
        var isExists = f.Exists;

        //Asssert
        Assert.IsFalse(isExists);
    });
}

e exemplo com a criação de objetos de teste complexos:

[TestMethod]
//Case 1
[TestProperty(nameof(FileDescriptor.FileVersionId), "673C9C2D-A29E-4ACC-90D4-67C52FBA84E4")]
//...
public void TestMethod2()
{
    //Arrange
    TestContext.For<FileDescriptor>().Fill(fi => fi.FileVersionId).Fill(fi => fi.Extension).Fill(fi => fi.Name).Fill(fi => fi.CreatedOn, new CultureInfo("en-US", false)).Fill(fi => fi.AccessPolicy)
        .ForEach(fileInfo =>
        {
            //Act
            var fileInfoString = fileInfo.ToString();

            //Assert
            Assert.AreEqual($"Id: {fileInfo.FileVersionId}; Ext: {fileInfo.Extension}; Name: {fileInfo.Name}; Created: {fileInfo.CreatedOn}; AccessPolicy: {fileInfo.AccessPolicy};", fileInfoString);
        });
}

Dê uma olhada nos métodos de extensão e no conjunto de amostras para obter mais detalhes.


2
Essa abordagem funciona, mas não cria casos de teste individuais para cada conjunto de parâmetros.
usr4896260

Você pode usar algo mais complexo como o valor TestProperty (por exemplo, "0-100"), analisar e manipular isso no corpo do teste.
Andrey Burykin

4

Há, é claro, outra maneira de fazer isso que não foi discutida neste segmento, ou seja, por herança da classe que contém o TestMethod. No exemplo a seguir, apenas um TestMethod foi definido, mas dois casos de teste foram feitos.

No Visual Studio 2012, ele cria dois testes no TestExplorer:

  1. DemoTest_B10_A5.test
  2. DemoTest_A12_B4.test

    public class Demo
    {
        int a, b;
    
        public Demo(int _a, int _b)
        {
            this.a = _a;
            this.b = _b;
        }
    
        public int Sum()
        {
            return this.a + this.b;
        }
    }
    
    public abstract class DemoTestBase
    {
        Demo objUnderTest;
        int expectedSum;
    
        public DemoTestBase(int _a, int _b, int _expectedSum)
        {
            objUnderTest = new Demo(_a, _b);
            this.expectedSum = _expectedSum;
        }
    
        [TestMethod]
        public void test()
        {
            Assert.AreEqual(this.expectedSum, this.objUnderTest.Sum());
        }
    }
    
    [TestClass]
    public class DemoTest_A12_B4 : DemoTestBase
    {
        public DemoTest_A12_B4() : base(12, 4, 16) { }
    }
    
    public abstract class DemoTest_B10_Base : DemoTestBase
    {
        public DemoTest_B10_Base(int _a) : base(_a, 10, _a + 10) { }
    }
    
    [TestClass]
    public class DemoTest_B10_A5 : DemoTest_B10_Base
    {
        public DemoTest_B10_A5() : base(5) { }
    }


3

Não consegui fazer com que o A DataRowAttributefuncionasse no Visual Studio 2015, foi com isso que acabei:

[TestClass]
public class Tests
{
    private Foo _toTest;

    [TestInitialize]
    public void Setup()
    {
        this._toTest = new Foo();       
    }

    [TestMethod]
    public void ATest()
    {
        this.Perform_ATest(1, 1, 2);
        this.Setup();

        this.Perform_ATest(100, 200, 300);
        this.Setup();

        this.Perform_ATest(817001, 212, 817213);
        this.Setup();

    }

    private void Perform_ATest(int a, int b, int expected)
    {
        //Obviously this would be way more complex...

        Assert.IsTrue(this._toTest.Add(a,b) == expected);    
    }
}

public class Foo
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}

A solução real aqui é usar apenas o NUnit (a menos que você esteja preso no MSTest como eu estou neste caso específico).


3
você deve dividir cada chamada de teste em um teste separado, para economizar seu tempo quando uma delas for interrompida. (que todos sabemos irá acontecer)
prata

Sim, claro. Na prática, é assim que isso seria feito. Neste caso, eu estava apenas ilustrando-o pela simplicidade
Brandon
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.