【问题标题】:How do test all combinations of parameters in DataRows如何测试 DataRows 中的所有参数组合
【发布时间】:2022-01-18 09:37:49
【问题描述】:

假设我有这样的测试方法:

[TestMethod]
[DataRow( 0, 0, 0 )]
[DataRow( 0, 0, 1 )]
[DataRow( 0, 1, 0 )]
[DataRow( 0, 1, 1 )]
[DataRow( 1, 0, 0 )]
[DataRow( 1, 0, 1 )]
[DataRow( 1, 1, 0 )]
[DataRow( 1, 1, 1 )]
public void ReallyCoolTest( int a, int b, int c )
{
    // some really cool test code that uses a, b, and c
}

这将针对等于 0 或 1 的 a、b 和 c 的所有组合进行测试。三个参数中只有两个值,并且需要 8 个 DataRow 行!

我真正想做的是这样的:

[TestMethod]
[DataMatrix( {0,1}, {0,1}, {0,1} )]
public void ReallyCoolTest( int a, int b, int c )
{
    // some really cool test code that uses a, b, and c
}

我想为每个参数指定一些值并测试所有组合。使用 MS 测试有类似的东西吗?

注意:我知道DataSource 属性。但是,我希望将值放在代码中,而不是在外部文件中。

【问题讨论】:

    标签: c# .net-core mstest


    【解决方案1】:

    您还可以在运行时使用DynamicData attribute 生成测试参数。您可以给出返回对象 [] 的 IEnumerable 的方法的名称。这些用作测试的参数。

    [DataTestMethod]
    [DynamicData(nameof(GetData), DynamicDataSourceType.Method)]
    public void ReallyCoolTest(int a, int b, int expected)
    {
       // ...
    }
    
    public static IEnumerable<object[]> GetData()
    {
      for(int i = 0; i <= 1; i++)
      {
         for(int j = 0; j <= 1; j++)
         {
            for(int k = 0; k <=1; k++)
            {
               yield return new object[] {i,j,k};
            }
         }
       }
    }
    

    【讨论】:

    • 我的主要问题是:1)数据不在测试函数旁边,2)我必须为每个测试定义一个数据函数。我会乱定义自己的属性,但如果我没有运气,我会接受这个答案,因为这确实有帮助。
    • 不幸的是,这是我所知道的最好的解决方案。我不知道这是否对您有帮助,但 Nunit 具有 Combinatorial 属性,这正是您要寻找的。​​span>
    【解决方案2】:

    我能想到的最好的是:

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System;
    using System.Collections.Generic;
    
    namespace UnitTestProject
    {
        [TestClass]
        public class TestThing
        {
            [CombinatorialTestMethod]
            [DataRow( 0 , 9 )]
            [DataRow( 1 , 2 )]
            [DataRow( 3 , 4 , 5 , 7)]
            public void TestMe( int a , int b , int c )
            {
                if ( b * 2 == c )
                    throw new Exception( "blah!" );
            }
        }
    
        public class CombinatorialTestMethodAttribute : TestMethodAttribute
        {
            private object[][] argsArrays = new object[][] { };
    
            private List<object[]> argumentsList = new( );
    
            public override TestResult[] Execute( ITestMethod testMethod )
            {
                // Get arrays of arguments, then construct arguments list
                List<object[]> argsArraysList = new( );
                foreach ( DataRowAttribute parameters in testMethod.GetAttributes<DataRowAttribute>( false ) )
                {
                    argsArraysList.Add( parameters.Data );
                }
                this.argsArrays = argsArraysList.ToArray( );
                this.ConstructArgumentsList( );
    
                // Invoke the test
                List<TestResult> results = new( );
                foreach ( object[] args in this.argumentsList )
                {
                    try
                    {
                        TestResult result = testMethod.Invoke( args );
                        results.Add( result );
                    }
                    catch ( Exception e )
                    {
                        results.Add( new TestResult( )
                        {
                            Outcome = UnitTestOutcome.Failed ,
                            TestFailureException = e ,
                        } );
                    }
                }
    
                return results.ToArray( );
            }
    
            private void ConstructArgumentsList( )
            {
                int num_params = this.argsArrays.Length;
    
                int[] indices = new int[num_params];
    
                bool done = num_params == 0;
                while ( !done )
                {
                    // Get next arguemnt combination
                    object[] args = new object[num_params];
                    for ( int i = 0 ; i < num_params ; i += 1 )
                    {
                        args[i] = this.argsArrays[i][indices[i]];
                    }
                    this.argumentsList.Add( args );
    
                    // increment indices
                    for ( int i = num_params - 1 ; i >= 0 ; i -= 1 )
                    {
                        indices[i] += 1;
                        if ( indices[i] >= this.argsArrays[i].Length )
                        {
                            indices[i] = 0;
    
                            if ( i == 0 )
                            {
                                done = true;
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
        }
    }
    

    我不会使用它,因为我对它还不是 100% 满意,但我可能会再弄一些东西,然后再发布一些东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-06
      • 2011-05-01
      • 1970-01-01
      • 2020-11-23
      相关资源
      最近更新 更多