【问题标题】:Unit testing both Excel formulas and VB with the same tool?使用相同的工具对 Excel 公式和 VB 进行单元测试?
【发布时间】:2016-05-11 21:48:30
【问题描述】:

是否有任何工具可以在 Excel 中对 Excel 公式和 Visual Basic 表单进行单元测试?我正在寻找可以做其中一个或另一个的方法,但不是两者兼而有之。例如,Rubberduck 看起来很有希望用于测试 VBA,但似乎不允许在 Excel 电子表格中测试公式。

【问题讨论】:

    标签: vba excel unit-testing


    【解决方案1】:

    我发现在 Excel 中“单元测试”功能的唯一方法是在您的工作簿中创建一个工作表,它在生活中的目的是成为验证页面。在此工作表中定义各种附加功能,用于查找工作簿中的边缘情况并检查添加等。

    保留一个 cmets 字段以及一个布尔成功字段非常有帮助,可以将它们聚合起来以在您的其他输入页面上放置自定义格式的消息,以提示用户“单元测试”失败。

    这种方法可以很好地使您的测试可重用并且对工作簿的最终用户透明。

    【讨论】:

      【解决方案2】:

      可以使用FlyingKoala 对 Excel 公式和 VBA 进行单元测试。 FlyingKoala 是xlwings 的扩展。

      xlwings 提供了一个 COM 包装器,它提供了从 Python 执行 VBA 的能力(通过让 Excel 运行它)。这是一个很棒的库/解决方案。来自 ZoomerAnalyitics 的受人尊敬的 Felix 写了一篇 blogpost 关于使用带有示例的 xlwings 对 VBA 进行单元测试的文章。

      FlyingKoala 使用库 (xlcalculator) 将 Excel 公式转换为 Python,然后可以在 Python 的 unittest 框架中进行单元测试。因此,可以评估公式并对照已知目标值检查 Excel 中的还是预定义的。

      在 Excel 运行时使用 FlyingKoala 进行单元测试公式的示例;

      import unittest
      import logging
      
      import xlwings as xw
      from flyingkoala import FlyingKoala
      from pandas import DataFrame
      from pandas import Series
      from numpy import array
      from numpy.testing import assert_array_equal
      from pandas.testing import assert_series_equal
      
      logging.basicConfig(level=logging.ERROR)
      
      class Test_equation_1(unittest.TestCase):
      
          def setUp(self):
      
              self.workbook_name = r'growing_degrees_day.xlsm'
      
              if len(xw.apps) == 0:
                  raise "We need an Excel workbook open for this unit test."
      
              self.my_fk = FlyingKoala(self.workbook_name, load_koala=True)
              self.my_fk.reload_koala('')
              self.equation_name = xw.Range('Equation_1')
      
              if self.equation_name not in self.my_fk.koala_models.keys():
                  model = None
                  wb = xw.books[self.workbook_name]
                  wb.activate()
                  for name in wb.names:
                      self.my_fk.load_model(self.equation_name)
                      if self.equation_name == name.name:
                          model = xw.Range(self.equation_name)
                          self.my_fk.generate_model_graph(model)
      
                  if model is None:
                      return 'Model "%s" has not been loaded into cache, if named range exists check spelling.' % self.equation_name
      
      
          def test_Equation_1(self):
              """First type of test for Equation_1"""
      
              xw.books[self.workbook_name].sheets['Growing Degree Day'].activate()
      
              goal = xw.books[self.workbook_name].sheets['Growing Degree Day'].range(xw.Range('D2'), xw.Range('D6')).options(array).value
      
              tmin = xw.books[self.workbook_name].sheets['Growing Degree Day'].range(xw.Range('B2'), xw.Range('B6')).options(array).value
              tmax = xw.books[self.workbook_name].sheets['Growing Degree Day'].range(xw.Range('C2'), xw.Range('C6')).options(array).value
              inputs_for_DegreeDay = DataFrame({'T_min': tmin, 'T_max': tmax})
              result = self.my_fk.evaluate_koala_model('Equation_1', inputs_for_DegreeDay).to_numpy()
      
              assert_array_equal(goal, result)
      
      
          def test_Equation_1_predefined_goal(self):
              """First type of test for Equation_1"""
      
              goal = Series([0.0, 0.0, 0.0, 0.0, 0.0, 5, 10, 15, 20])
      
              tmin = [-20, -15, -10, -5, 0, 5, 10, 15, 20]
              tmax = [0, 5, 10, 15, 20, 25, 30, 35, 40]
              inputs_for_DegreeDay = DataFrame({'T_min': tmin, 'T_max': tmax})
              result = self.my_fk.evaluate_koala_model('Equation_1', inputs_for_DegreeDay)
      
              assert_series_equal(goal, result)
      
      
          def test_VBA_Equation_1(self):
              """
              The function definition being called;
      
              Function VBA_Equation_1(T_min As Double, T_max As Double) As Double
                  VBA_Equation_1 = Application.WorksheetFunction.Max(((T_max + T_min) / 2) - 10, 0)
              End Function
              """
      
              goal = 20
      
              vba_equation_1 = xw.books[self.workbook_name].macro('VBA_Equation_1')
              result = vba_equation_1(20.0, 40.0)
      
              self.assertEqual(goal, result)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-09-20
        • 1970-01-01
        • 1970-01-01
        • 2016-02-25
        • 2019-08-25
        • 1970-01-01
        • 2019-07-08
        • 1970-01-01
        相关资源
        最近更新 更多