如何测试 DataRows 中的所有参数组合

Posted

技术标签:

【中文标题】如何测试 DataRows 中的所有参数组合【英文标题】:How do test all combinations of parameters in 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 属性。但是,我希望将值放在代码中,而不是在外部文件中。

【问题讨论】:

【参考方案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% 满意,但我可能会再弄一些东西,然后再发布一些东西。

【讨论】:

以上是关于如何测试 DataRows 中的所有参数组合的主要内容,如果未能解决你的问题,请参考以下文章

如何使用lambda表达式过滤DataRows?

tidyverse:Chi Square适用于所有列的组合

使用awk命令循环查找并修改后输出。

您如何正确快速地比较 Datarows / Datatables?

具有标签的 DataRows 的自定义 DataTable

Three.js:无法更改 dat.GUI 中的值