rubberduck-vba / Rubberduck

Every programmer needs a rubberduck. COM add-in for the VBA & VB6 IDE (VBE).
https://rubberduckvba.com
GNU General Public License v3.0
1.92k stars 301 forks source link

When Excel is in "Design Mode", all tests are skipped. #5683

Open GenericBIM opened 3 years ago

GenericBIM commented 3 years ago

Rubberduck version information

Version 2.5.1.5557 OS: Microsoft Windows NT 10.0.19042.0, x64 Host Product: Microsoft Office x64 Host Version: 16.0.13628.20448 Host Executable: EXCEL.EXE

Description When Excel is in "Design Mode", all tests are skipped with the message:

"Something went wrong when trying to run @ModuleInitialize. Module skipped."

To Reproduce Steps to reproduce the behavior:

  1. Add a TestModule.
  2. Add a TestMethod.
    
    Private Sub TestMethod1()
    On Error GoTo TestFail
    'Assert:
    Assert.Succeed

TestExit: Exit Sub TestFail: Assert.Fail "Test raised an error: #" & Err.number & " - " & Err.Description End Sub



3. Run test, it should pass.
4. Return to the Excel UI, on the 'Developer' tab, 'Controls' panel, turn on 'Design Mode'.
5. Return to the Rubberduck Text Explorer, Run the test, now the test is skipped with the message:
> "Something went wrong when trying to run @ModuleInitialize. Module skipped."

**Expected behavior**
Tests should not fail if the Excel UI is in 'Design Mode' OR the failure message should be clear 'Design Mode' should be disabled.

Thank you,
retailcoder commented 3 years ago

Thank you for this feedback!

We unfortunately don't get to know whether the COMException we get is because of the host being in design mode. In fact we're getting a COMException no matter what went wrong with running the VBA code. Per the logged stack trace, the exception is thrown when getting the accessor for the standard module, very deep inside the internal API:

2021-04-01 23:45:43.4353;ERROR-2.5.1.0;Rubberduck.UnitTesting.TestEngine;Unexpected COM exception while initializing tests for module VBAProject.TestModule1. The module will be skipped.;System.Runtime.InteropServices.COMException (0x800A9D9F): Exception from HRESULT: 0x800A9D9F
   at Rubberduck.VBEditor.ComManagement.TypeLibs.IVBEComponent.GetStdModAccessor()
   at Rubberduck.VBEditor.ComManagement.TypeLibs.TypeInfoVBEExtensions.GetStdModAccessor() in E:\Dev\GitHub\Rubberduck\Rubberduck.VBEEditor\ComManagement\TypeLibs\TypeInfoVBEExtensions.cs:line 131
   at Rubberduck.VBEditor.ComManagement.TypeLibs.TypeInfoVBEExtensions.StdModExecute(String name, Object[] args) in E:\Dev\GitHub\Rubberduck\Rubberduck.VBEEditor\ComManagement\TypeLibs\TypeInfoVBEExtensions.cs:line 151
   at Rubberduck.VBEditor.ComManagement.TypeLibs.VBETypeLibsAPI.ExecuteCode(ITypeInfoWrapper standardModuleTypeInfo, String procName, Object[] args) in E:\Dev\GitHub\Rubberduck\Rubberduck.VBEEditor\ComManagement\TypeLibs\Public\TypeLibsAPI.cs:line 290
   at Rubberduck.VBEditor.ComManagement.TypeLibs.VBETypeLibsAPI.ExecuteCode(ITypeLibWrapper projectTypeLib, String standardModuleName, String procName, Object[] args) in E:\Dev\GitHub\Rubberduck\Rubberduck.VBEEditor\ComManagement\TypeLibs\Public\TypeLibsAPI.cs:line 261
   at Rubberduck.UnitTesting.VBEInteraction.RunDeclarations(ITypeLibWrapper typeLib, IEnumerable`1 declarations) in E:\Dev\GitHub\Rubberduck\Rubberduck.UnitTesting\UnitTesting\VBEInteraction.cs:line 32
   at Rubberduck.UnitTesting.TestEngine.RunWhileSuspendedOnUiThread(IEnumerable`1 tests) in E:\Dev\GitHub\Rubberduck\Rubberduck.UnitTesting\UnitTesting\TestEngine.cs:line 279

There is little we can do to actually "fix" this, because it appears Excel snaps itself out of design mode when you invoke a macro manually, but not when Rubberduck does its thing (which works regardless of what host we're in, and that's important!):

  1. Toggle design mode ON from the developer tab
  2. Execute any Public Sub procedure from the immediate toolwindow
  3. Design mode has been toggled OFF even if the invoked procedure has no executable statements

This absolutely is a very valuable piece of knowledge that does belong in the unit testing reference and documentation.

bclothier commented 3 years ago

Can we make use of hresult 0x800A9D9F? It seems unique and fairly specific. Googling seems to yield similar situations where the hosts cannot run, so I think we can at least set up test engine to check the hresult and report accordingly.

retailcoder commented 3 years ago

@bclothier looks like that could probably work!