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.91k stars 299 forks source link

Unit Tests does not create a test module #5351

Open SmileyFtW opened 4 years ago

SmileyFtW commented 4 years ago

Rubberduck version information Version 2.5.0.5288 OS: Microsoft Windows NT 10.0.18362.0, x64 Host Product: Microsoft Office x86 Host Version: 16.0.12325.20288 Host Executable: EXCEL.EXE

Description RD doesn't create a Test Module

To Reproduce Steps to reproduce the behavior:

  1. In RD Menu>Unit Tests>Test Module
  2. Nothing happens; no test module is created.

Expected behavior A test module is expected to be created.

Logfile

RubberduckLog.txt

MDoerner commented 4 years ago

The relevant part from the log seems to be the following.

2020-01-14 15:46:06.3125;ERROR-2.5.0.5288;Rubberduck.UI.UnitTesting.ComCommands.AddTestModuleCommand;System.Runtime.InteropServices.COMException (0x800A802D): Name conflicts with existing module, project, or object library
   at Microsoft.Vbe.Interop._References.AddFromFile(String FileName)
   at Rubberduck.VBEditor.SafeComWrappers.VBA.References.AddFromFile(String path) in C:\projects\rubberduck\Rubberduck.VBEditor.VBA\SafeComWrappers\VB\References.cs:line 51
   at Rubberduck.UnitTesting.VBEInteraction.EnsureProjectReferencesUnitTesting(IVBProject project) in C:\projects\rubberduck\Rubberduck.UnitTesting\UnitTesting\VBEInteraction.cs:line 109
   at Rubberduck.UnitTesting.CodeGeneration.TestCodeGenerator.AddReferenceIfNeeded(IVBProject project, IUnitTestSettings settings) in C:\projects\rubberduck\Rubberduck.UnitTesting\CodeGeneration\TestCodeGenerator.cs:line 109
   at Rubberduck.UnitTesting.CodeGeneration.TestCodeGenerator.AddTestModule(IVBProject project, Declaration stubSource) in C:\projects\rubberduck\Rubberduck.UnitTesting\CodeGeneration\TestCodeGenerator.cs:line 67
   at Rubberduck.UnitTesting.CodeGeneration.TestCodeGenerator.AddTestModuleToProject(IVBProject project, Declaration stubSource) in C:\projects\rubberduck\Rubberduck.UnitTesting\CodeGeneration\TestCodeGenerator.cs:line 55
   at Rubberduck.UI.UnitTesting.ComCommands.AddTestModuleCommand.OnExecute(Object parameter) in C:\projects\rubberduck\Rubberduck.Core\UI\UnitTesting\ComCommands\AddTestModuleCommand.cs:line 86
   at Rubberduck.UI.Command.CommandBase.Execute(Object parameter) in C:\projects\rubberduck\Rubberduck.Core\UI\Command\CommandBase.cs:line 85;System.Runtime.InteropServices.COMException (0x800A802D): Name conflicts with existing module, project, or object library
   at Microsoft.Vbe.Interop._References.AddFromFile(String FileName)
   at Rubberduck.VBEditor.SafeComWrappers.VBA.References.AddFromFile(String path) in C:\projects\rubberduck\Rubberduck.VBEditor.VBA\SafeComWrappers\VB\References.cs:line 51
   at Rubberduck.UnitTesting.VBEInteraction.EnsureProjectReferencesUnitTesting(IVBProject project) in C:\projects\rubberduck\Rubberduck.UnitTesting\UnitTesting\VBEInteraction.cs:line 109
   at Rubberduck.UnitTesting.CodeGeneration.TestCodeGenerator.AddReferenceIfNeeded(IVBProject project, IUnitTestSettings settings) in C:\projects\rubberduck\Rubberduck.UnitTesting\CodeGeneration\TestCodeGenerator.cs:line 109
   at Rubberduck.UnitTesting.CodeGeneration.TestCodeGenerator.AddTestModule(IVBProject project, Declaration stubSource) in C:\projects\rubberduck\Rubberduck.UnitTesting\CodeGeneration\TestCodeGenerator.cs:line 67
   at Rubberduck.UnitTesting.CodeGeneration.TestCodeGenerator.AddTestModuleToProject(IVBProject project, Declaration stubSource) in C:\projects\rubberduck\Rubberduck.UnitTesting\CodeGeneration\TestCodeGenerator.cs:line 55
   at Rubberduck.UI.UnitTesting.ComCommands.AddTestModuleCommand.OnExecute(Object parameter) in C:\projects\rubberduck\Rubberduck.Core\UI\UnitTesting\ComCommands\AddTestModuleCommand.cs:line 86
   at Rubberduck.UI.Command.CommandBase.Execute(Object parameter) in C:\projects\rubberduck\Rubberduck.Core\UI\Command\CommandBase.cs:line 85
SmileyFtW commented 4 years ago

If I knew what file (or files) are duplicates could deleting one (or both) resolve this?

SmileyFtW commented 4 years ago

In an effort to resolve this I remove RD (Apps & Programs); Shut down and then restarted. Then downloaded the latest pre-release (2.5.0.5296) and installed it. The issue remains and Vogel612's culprit seems to be the one as it is the last entry in the trace.

MDoerner commented 4 years ago

The problem here seems to have been a stale reference to the RD unit testing library in the project itself. When we tried to add the reference, it failed because a reference with the same project name was already present.

We usually remove the reference, if it already exists here, but that did not work for some reason.

The issue can be resolved by manually removing the reference to RD. Adding the next test module will add the correct reference. See chat.

MDoerner commented 4 years ago

I did some testing with a debugger attached. The problem is the following.

Accoringly, FindReferenceByName never finds the reference and, thus, never removes it. It works if the reference is up to date because we have another check that verifies that a reference with the same path does not exist already.

We should align the two values.

As far as I remember, for a long time the RD unit testing library was also called Rubberduck in the project explorer. Then, the check worked out of this coincidence.

bclothier commented 4 years ago

From what I see in the EnsureProjectReferencesUnitTesting, it does not attempt to add by GUID (e.g. References.AddFromGuid). It only uses the file (References.AddFromFile). We already know the GUID so we should use that instead. We might be able to avoid this problem by removing & adding using GUID, then falling back to the path if we cannot use GUID (e.g. not in registry). Furthermore, when we search the references, we use names but not GUID. Again, that should be using GUID first then falling back to name.

Note that when a reference is broken, GUID might not be reliable to read off, so may need to be handled accordingly.

Regarding the names - that is normal and has been that way - the references shows the descriptive name, (e.g. Reference.Description property) which is Rubberduck AddIn but the library's programmatic name (e.g. Reference.Name property) is Rubberduck. That said, one possibility is that if the file was compiled with the release build but then later loaded into a host running a debug build that does not have MIDL, there will be few minor differences because without MIDL, we cannot make the changes to the IDL as handled in the IDLListener. That would only happen on the developers running without the C++ build tools.


Note: the links point to Access.References but it's basically the same as VBIDE.References for which I could not find quickly.

MDoerner commented 4 years ago

If the value from the registry is indeed the description, we can simply change to FindByDescription.

SmileyFtW commented 4 years ago

Since y'all are working on deeper issues with this I will leave closing this up to y'all. I am up and functioning again, so that is good enough for me... Thanks!