« first day (1011 days earlier)      last day (2169 days later) » 
00:00 - 19:0019:00 - 00:00

7:07 PM
> I see your point about flipping the inspection, but IMO we need *both* perspectives, for 2 reasons.

- Procedure level attributes are susceptible to being deleted if you edit the signature or first line of a procedure
- Copying/Moving the codepane text of a module or procedure isn't enough to also copy the underlying attributes to the target

If the annotation survives the edit, then RD could reimplement the VB Attribute
> Also, I'm unsure how we'll make this work in document-type modules.
> Document-type modules are simply excluded; they can't have attributes, simple as that. Perhaps we could have an inspection to warn about such annotations in document modules.

> *If the annotation survives the edit, then RD could reimplement the VB Attribute*

My view is that the annotations dictate what attributes should be present; if there's an attribute without a corresponding annotation, then there's something implicit going on that an inspection needs to reveal; if there's an annotat
> Document-type modules are simply excluded; they can't have attributes, simple as that. Perhaps we could have an inspection to warn about such annotations in document modules.

> *If the annotation survives the edit, then RD could reimplement the VB Attribute*

My view is that the annotations dictate what attributes should be present; if there's an attribute without a corresponding annotation, then there's something implicit going on that an inspection needs to reveal; if there's an annotat
> Document-type modules are simply excluded; they can't have attributes, simple as that. Perhaps we could have an inspection to warn about such annotations in document modules.

> *If the annotation survives the edit, then RD could reimplement the VB Attribute*

My view is that the annotations dictate what attributes should be present; if there's an attribute without a corresponding annotation, then there's something implicit going on that an inspection needs to reveal (and a quick-fix can a
 
@ThunderFrame attributes need to be injected at the pre-processing stage, before parsing of the actual in-VBE code even begins
heck, we could even inject the missing annotations during pre-processing
and then no need to inspect anything
e.g. we export the module, and process this:
Attribute VB_Name = "SqlCommand"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Private converter As New AdoValueConverter
Private connString As String
Private resultFactory As New SqlResult
Option Explicit

Public Property Get ConnectionString() As String
    ConnectionString = connString
End Property

Public Property Let ConnectionString(ByVal value As String)
    connString = value
End Property

Public Property Get ParameterFactory() As AdoValueConverter
we turn it into this:
Attribute VB_Name = "SqlCommand"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
'@PredeclaredId
Private converter As New AdoValueConverter
Private connString As String
Private resultFactory As New SqlResult
Option Explicit

Public Property Get ConnectionString() As String
    ConnectionString = connString
End Property

Public Property Let ConnectionString(ByVal value As String)
    connString = value
End Property
then re-import it and resume pre-processing, then proper processing
on the flipside - we export the module and see this:
Attribute VB_Name = "SqlCommand"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
'@PredeclaredId
Private converter As New AdoValueConverter
Private connString As String
Private resultFactory As New SqlResult
Option Explicit

Public Property Get ConnectionString() As String
    ConnectionString = connString
End Property

Public Property Let ConnectionString(ByVal value As String)
    connString = value
End Property
we need to pick up the @Description annotation right there and then, and inject the attribute:
Attribute VB_Name = "SqlCommand"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
'@PredeclaredId
Private converter As New AdoValueConverter
Private connString As String
Private resultFactory As New SqlResult
Option Explicit

Public Property Get ConnectionString() As String
    ConnectionString = connString
End Property

Public Property Let ConnectionString(ByVal value As String)
    connString = value
End Property
 
7:23 PM
When a unit test fails, how do I get it to show the failed message in the Test Explorer window?
 
^ so this is what we re-import for further processing
@IvenBach you mean a custom message?
are you early-binding Rubberduck?
 
I am pretty sure I'm late binding.
 
ok, doesn't matter. with early binding you'd see the arguments
    /// <summary>
    /// Fails the assertion without checking any conditions.
    /// </summary>
    /// <param name="message">An optional message to display.</param>
    void Fail(string message = null);
so Assert.Fail "this message will show up in the test explorer when the test fails"
    /// <summary>
    /// Verifies that the specified condition is <c>true</c>. The assertion fails if the condition is <c>false</c>.
    /// </summary>
    /// <param name="condition">Any Boolean value or expression.</param>
    /// <param name="message">An optional message to display if the assertion fails.</param>
    void IsTrue(bool condition, string message = null);
 
@Mat'sMug That is not the behavior I'm experiencing.
 
all Assert methods have an optional message parameter
@IvenBach how is the test failing?
what does it say?
 
7:26 PM
If Not AreCellsEqual Then
    Assert.Fail "Fails on table row: " & tblRow
    Exit For
End If
The message in Test Explorer is IsTrue assertion failed.
even though i have the Assert.Fail <Msg>
 
the test is failing an Assert.IsTrue call
not Assert.Fail
 
normally a unit test has 1 reason to fail, i.e. one single Assert call
 
@Duga YEAH!!
 
7:28 PM
> Well, I just *exported* this from my project...

```vb
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "Sheet1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_Description = "The Sheet with the Foo"
Option Explicit

Sub Foo(Bar As String)
Attribute Foo.VB_Description = "This does the Foo with the Bar"
Beep
End Sub
```
 
My test is going through a table and performing the same test on everything in the table.
 
It's checking to see if a cell reference, via formula, is the same as the static textual cell location.
 
@IvenBach I'd wait for my next PR to merge before you write that. ;-)
 
are you saying there is no Assert.IsTrue call anywhere in that test?
something is REALLY messed up if that's the case
 
7:30 PM
> Still there.

Error: Option Explicit is not specified in 'Sheet2' - (testRubberduck.xlsm) VBAProject.Sheet2, line 1
 
For tblRow = 1 To tblBodyRange.Rows.Count
Dim AreCellsEqual As Boolean
AreCellsEqual = (tblBodyRange(tblRow, referenceCellColumn) = tblBodyRange(tblRow, expectedCellColumn))
Assert.IsTrue AreCellsEqual
If Not AreCellsEqual Then
Assert.IsFail "Fails on table row: " & tblRow
Exit For
End If
Next
 
Assert.IsTrue AreCellsEqual
^ that's what's failing your test
Assert calls determine the outcome of a test - if a single one fails, the test fails.. so you can't have code that requires a failed assertion to run! remove the Assert.IsTrue call if you want the rest of the test to mean anything
 
@Duga Doing "the Foo with the Bar" beeps?
 
^lol
@IvenBach I'd hold off on that test until you can do this.
 
7:37 PM
> I have a VBA code profiler addin I'm offering free at

https://sysmod.wordpress.com/2017/03/09/free-add-in-to-profile-vba-speed-and-coverage/

If it was of interest, and if someone was willing to convert the code to C#, you can have the source.

It's not difficult code, the worst for me was the parsing and you have that solved already.

It simply injects statements that collect timing data so at the end you can see how long each proc took, or what lines were covered in the test.

I think someone did a more clever solution in Access by hacking into the VBA execution and intercepting that.
thoughts?
 
Don't the unit tests already do that? Judging by the description it looks like it's adding a bunch of VBA timer code everywhere.
 
IKR
 
Looks like he's timing all the procs
 
I do have some code to try and trip it up with though. Muahahaha!
 
Exit Function would trip it up, no?
 
7:42 PM
@Comintern That looks helpful. I'm almost done with mine though. It's helping me learn unit testing by building the tests.
 
Or End.
Or:
Exit _
Sub
 
lol
 
Using error handling for flow control would do it nicely too.
 
or MsgBox - there goes your timing
 
lol
 
7:45 PM
although, MsgBox in a unit test is a killer as well
 
inject your msgbox
 
"The profiler is showing a choke point in Sub Foo - we need to improve user reaction time."
 
it's from @SystemsModelling
 
The "Snakes on a plane!" message is taking users some time to process.
 
7:59 PM
OK. Let's see if this thing works with a selection our most out there test code. :saves work:
 
    'Assert:
    Dim tblRow As Long
    For tblRow = 1 To tblBodyRange.Rows.Count
        Dim AreCellsEqual As Boolean
        AreCellsEqual = (tblBodyRange(tblRow, referenceCellColumn) = tblBodyRange(tblRow, expectedCellColumn))
        'Assert.IsTrue AreCellsEqual
        If Not AreCellsEqual Then
            Err.Raise vbObjectError + 1, Description:="Fails on: " & tblBodyRange(tblRow, 1) & " | Row: " & tblRow
            'Assert.IsFail AreCellsEqual, "Fails on table row: " & tblRow
            'Exit For
Is there anything terrible about ^?
 
lol, using runtime errors for flow control determining test outcome?
the TestFail label should really only ever run when the tested code raises an unexpected error
 
I'm just trying to get this unit test to work...
 
:)
Assert.IsFail should be Assert.Fail
uncomment it - and remove the AreCellsEqual argument.. Assert.Fail only has a message argument.
and remove the Err.Raise call
    If Not AreCellsEqual Then
        Assert.Fail "Fails on table row: " & tblRow
        Exit For
    End If
 
That's making a lot more sense what you were saying earlier with that edit.
Some Most of my code I present must seem so clunky to you.
 
8:05 PM
just a little ;-)
 
I'm figuring it out as I go along, that's the main issue.
should unit tests do anything other than test? IE suggest a fix point to where the issue is? In my case which cell the information is housed in.
 
tests should be so focused that a failing test tells you (by its name) what the problem is
e.g. with that test you're testing the outcome, but not the logic that determines that outcome
it's like our blackbox inspection tests that break when there's a parser or resolver bug
it's bad because it makes a test fail for more than one reason
OTOH, depends how religious you want to be about it
 
Yeah, I broke the profiler. I didn't even pull out the good stuff.
 
@Comintern I CC'd you on my reply
 
:-)
It doesn't seem to like If statements that much. For some reason it doesn't tag them for coverage.
 
8:12 PM
is there something to do with it?
 
@Mat'sMug So a test should only do a test. No suggestion, color cell where the offending problem arises from, etc...
 
I think it might have been either this:
 
(haven't looked)
 
Public Sub Test()
    If Foo = 42 Then: Bar = Foo: Else: Baz = Foo:
'    End If
End Sub
The VBA project is locked.
 
that shouldn't be a big problem :)
 
8:12 PM
lol
 
easier to open than parse an inline If
 
Whatever it is is an invalid procedure call followed by some cryptic "Unexpected error (40182)".
 
@IvenBach a test should control all inputs and dependencies anyway
 
@ThunderFrame I always forget. Is it considered "inline" if you have instruction separators?
 
I wouldn't
I don't think the grammar and parser do either ;-)
 
8:17 PM
My inline is a vertical line:
If _
foo _
Then _
bar _
Else _
baz
 
that's... that's mean!
 
If _
foo _
Then _
bar _
Else _
baz ' _
End If
'Comment saves the OCD day
 
^ how does the indenter like that one?
how does the original Smart Indenter like that one
 
I don't even want to know.
At least it would simply, and proudly, carry on an established VBx/VBA tradition of very slowly mangling it until it no longer compiled.
 
8:34 PM
LOL
 
^ that's not a factory default
 
Unless it was bound for a unicode market.
 
Unicode Working Group market
 
Either that or they want to keep mobile devices off of it. I'm having a hard time finding those on my phone's keyboard.
 
@Comintern haha
 
8:48 PM
I'm betting it's Finnish for Foo Wifi (powered by Nokia)
 
@Comintern You don't need to on mine. It just shows it as available, and I just have to click it.
 
@Comintern That's starting to mighty nice...
It will solve one of my tests but not the other.
 
@IvenBach I have a quick question for you whenever's a good time.
 
Within a unit test, the moment an individual test fails (assuming you have multiple checks within the test) should the test proceed stop?
IE:
    Public Sub SomeTest()
        Assert.IsTrue expected1, result1
        Assert.IsTrue expected2, result2
        Assert.IsTrue expected3, result3
    End Sub
 
@ThunderFrame why do they even broadcast that SSID
@IvenBach the thing is that RD does not control execution of code in the IDE
 
8:53 PM
In general.
I know RD is bound be the IDE but in other languages would it stop at Assert.IsTrue expected1, result1 were they to not be true?
@puzzlepiece87 If it's something I can help with I'll try.
 
the result of a test is determined by the Assert calls we collect while it's running
if all Assert calls succeed, the test passes
if ONE Assert call fails, the test fails
it will run to completion though
it has to
a failed assert doesn't raise a runtime error
in .net a failed assert throws an AssertFailedException and it's handled totally differently
 
What about C#? Which is my only other experience.
 
29 secs ago, by Mat's Mug
in .net a failed assert throws an AssertFailedException and it's handled totally differently
 
So in .net you'd be able to handle it as you wanted?
 
@Mat'sMug I guess it's a little more unique than John's iPhone
 
8:56 PM
the test framework handles it
if your test code wraps Assert calls in try/catch(AssertFailedException) calls, you're doing it very very wrong
 
@IvenBach You'll probably be able to! I'll keep Googling while you all finish this conversation.
 
@Mat'sMug That's where my mental disconnect happens. Aren't the unit tests the framework?
 
the tests are user code
the framework is what runs them and determines whether they pass or fail based on what happens when they run
 
So for RD the framework is VBA and C# is .net?
 
for RD tests the framework is the Rubberduck type library itself; in C# it depends - we currently use MS-Test
the Assert class is part of the testing framework
 
9:01 PM
For tblRow = 1 To tblBodyRange.Rows.Count
    Dim cellExpected As Range
    Set cellExpected = tblBodyRange(tblRow, expectedCellColumn)

    Dim cellReference As Range
    Set cellReference = tblBodyRange(tblRow, referenceCellColumn)

    Dim AreCellsEqual As Boolean
    AreCellsEqual = (cellReference.Value2 = cellExpected.Value2)

    If Not AreCellsEqual Then
        Union(cellReference, cellExpected).Interior.Color = VIOLATION_COLOR
        Assert.Fail "Fails on: " & tblBodyRange(tblRow, 1) & " | Row: " & cellReference.Row
In my test is it egregious to have Exit For so it stops on the 1st error it encounters and notes it in the Text Explorer window.
Or would it be preferable for it to continue and run through all?
I feel hope that once I get my heard wrapped around this question then the rest of my issues will all mostly be taken care of.
@puzzlepiece87 I can take a stab at your question.
 
Thanks
I'm trying to call a sub in my class module from my main module, but VBE doesn't like that. Am I doing it incorrectly or am I not supposed to do it at all?
 
@IvenBach nah that's fine - IMO even @Comintern's SequenceEquals implementation should do that
 
@Mat'sMug Thanks :+1:
 
Let's say it's SubName1 - in the main module, at the appropriate place, I just wrote SubName1 to call it.
 
a test can make 200 Assert calls - it only takes 1 failed to fail the test; thus there's no reason to keep going if you know it's failling
 
9:07 PM
So far I was looking at this question to see if I need to use CallByName or Application.Run: stackoverflow.com/questions/2695198/…
 
@Mat'sMug That superbly answers my question. Fail fast fail often!
 
@puzzlepiece87 what did you name your class?
a class doesn't exist, it's just a blueprint for an object.
if you have class Something and you want to call its DoSomething method, you need to first create an instance of it:
 
Let's say I named the class CName1
 
Dim foo As Something
Set foo = New Something
foo.DoSomething
ever used a Collection?
 
okay, thank you
 
9:08 PM
Collection is a class
you can't do Collection.Add
 
I generally use dictionaries but I can use a collection
 
or a dictionary - same thing
they're blueprints for objects
unless the class has a predeclared id
like a UserForm does
that's how you can do UserForm1.Show without Newing it up
but that's bad
because it uses the "default instance"
 
Okay. I'm probably misusing my class module then
What I did was use a class to act as a table basically, where each property is a column
Then I wrote stuff I wanted to do with that class and those properties underneath the setup code as SubName1
 
a class can be just about anything you want to make it
that's what's so cool about 'em - they're building blocks for your own API
 
So for mine, I have all the different settings for the SQL injection in the class - my intention is that when I start the program, the class is set up, and then I can adjust the values by calling either SubName1 or SubName2
But when I tried calling SubName1 it didn't work
 
9:12 PM
of course it won't
 
Should I just move SubName1 from the class module to the main module?
 
depends how you want to call it and whether you want that state to exist in an instance/object, or in global scope in a module
there's no right/wrong answer here
 
Okay cool, I think I'll move it to the main module - I want global scope I believe.
 
Dim state As New CName1
state.Subname1
 
I'm adjusting the properties of the class permanently (unless I adjust them again), not temporarily.
 
9:14 PM
permanent/temporary is a confusing way to think about global/instance
 
My instinct is that that would only be appropriate if I had a CName2 since my CName1 properties have nothing to do with SubName1
 
probably
 
Sorry, you are right - I think I want the state to exist in global scope
 
a class should do something, not just hold state. although, often it's nice to have a "record" class to represent, say, a row in some data table
 
Oh, then I am definitely misusing it.
 
9:17 PM
actually "should do something" is wrong, that's what a method does
 
My class doesn't do anything besides hold state, and I was going to manipulate its state.
 
a class encapsulates state, and exposes methods to act upon it
 
Okay, going to re-read the definition of encapsulation before deciding if my class encapsulates state or not
 
if all the state is public and manipulated from outside the class, it's not quite encapsulated ;-)
TTGH
 
No, my class doesn't encapsulate anything
Blast, okay, I'll keep figuring this out
Thanks @Mat'sMug and @IvenBach
Enjoy your evenings :)
 
9:20 PM
Don't think I answered anything there.
 
> Trying to set up source control. Created a repo online. Try to sync code to new repo. I get the username and password prompt. When I enter in my login and click Ok. All of Access crashes. It also causes a "File not found" error when I try to reopen the code window of the database.
 
@IvenBach It all helps, and I appreciate your time and attention
 
Odd... It seems that renaming a test module is what's causing excel to have problems.
Even when the module name is <31 characters.
 
9:47 PM
> Source Control initial setup is ...*picky* to say the least - we have a dedicated project to *git* it on track.

I was able to get it to work (through some trial & error) and documented the steps in the [wiki](https://github.com/rubberduck-vba/Rubberduck/wiki/Source-Control:-Getting-Started) - did you follow the steps described there?
 
@IvenBach that would be renaming any module - it being a test module shouldn't make a difference
 
Ok. I'm having odd behavior and can't figure out why, just that it happens after renaming my test module.
 
Whenever RD starts going wonky, saving your work and restarting the host is a good idea
 
I can rename the test module and anything longer than 'TestModule1' and it doesn't work. Any name length <= 'TestModule1' and it doesn't have any problem running.
@Mat'sMug I've done that a few times now. It seems like the parser or something is left lingering. When I open up Task Manager and watch it after a rename and it parses it goes from ~3% cpu usage to 24%+
If I rename again or try parsing it usually goes up to 50%+ and after that it stays at 100% usage. Only way to resolve is restarting Excel.
Actually, it seems to happen any time I parse.
 
10:22 PM
@IvenBach How long is the full filename of the file in which you try to add the test method? (It is an excel file, right?)
For me the CPU load also goes up when doing fast consecutive parsing runs, but it never reaches 100%.
This behaviour is actually to be expected since the inspections cannot be canceled at the moment; they are just piling up.
In my test project, it takes several minutes for them to finish, and that is on the first parse already.
 
I really gotta get that rewriter stuff done
 
It would be really nice to be able to just cancel them.
 
I can occasionally hit 100% CPU usage in my VM during GC if I don't allocate enough memory or CPU cores to it but it's only when it's doing garbage collection. That could be an artifact of the profiler though.
 
I guess it would also be good to make it possible to do parsing runs without triggering the inspections.
There is not too much sense in running them after every refactoring.
 
> Not sure if the following is possible, but from a user perspective this would be nice.

Since VBA does have interfaces, make an interface a requirement of the Mocking. Then annotate the interface with something like '@MockInterface allowing the RubberDuck parsing to detect the interface. Also annotate each member with @MockMethod and @MockPropertySet/@MockPropertyGet.

```
'@MockInterface
Option Compare Database
Option Explicit

'@MockPropertyGet
Public Property Get MyProperty() a
 
10:28 PM
Who wants to search for the open issue?
 
> Not sure if the following is possible, but from a user perspective this would be nice.

Since VBA does have interfaces, make an interface a requirement of the Mocking. Then annotate the interface with something like '@MockInterface allowing the RubberDuck parsing to detect the interface. Also annotate each member with @MockMethod and @MockPropertySet/@MockPropertyGet.

```
'@MockInterface
Option Compare Database
Option Explicit

'@MockPropertyGet
Public Property Get MyProperty() a
 
Ah, it is already in the right place.
 
@M.Doerner Found it. It's #1550. :-D
 
> Not sure if the following is possible, but from a user perspective this would be nice.

Since VBA does have interfaces, make an interface a requirement of the Mocking. Then annotate the interface with something like '@MockInterface allowing the RubberDuck parsing to detect the interface. Also annotate each member with @MockMethod and @MockPropertySet/@MockPropertyGet.

```
'@MockInterface
Option Compare Database
Option Explicit

'@MockPropertyGet
Public Property Get MyProperty() a
 
@Duga I would love to drop some hooks on the VBA runtime to just intercept the calls...
 
10:36 PM
> Yes, I am following those steps exactly. When prompted for my username and password, Access crashes. Note, I am using Access 2013 x64.
 
Is it really a good idea to call the tests in Excel with the full specifier, i.e. including the full filename? Sure, it prevents naming collisions like in Access, but the Application.Run method has a hard limit of 255 characters for the string passed to it.
@Duga I do not see the advantage of having dedicated mocking annotations. We are parsing everything anyway. So, we should be able to mock whatever we want, as long as it is not built-in or has those evil underscored in the name of a public member.
 
Couple options there I guess - we could test the length of the passed method and omit the filename if it was too long, we could inject the parser state and check for duplicates, or we could just new up a Workbook and call them directly.
 
Well, that is when we are able to properly inject classes.
I guess, the first option would be quite easy to implement.
 
Or wait, we don't use Ninject for that.
 
It's in the ExcelApp class.
 
10:48 PM
We can just pass the parser state as a parameter to the *App.Run methods.
 
We are assembling the string to pass from the QMN and the document name right there in ExcelApp.cs. I think we do not have to pass anything.
 
@Duga crap
 
We could just do this:
        protected virtual string GenerateMethodCall(dynamic declaration)
        {
            var qualifiedMemberName = declaration.QualifiedName;
            var module = qualifiedMemberName.QualifiedModuleName;

            var documentName = string.IsNullOrEmpty(module.ProjectPath)
                ? declaration.ProjectDisplayName
                : Path.GetFileName(module.ProjectPath);

            string candidateString = string.IsNullOrEmpty(documentName)
                ? qualifiedMemberName.ToString()
 
@M.Doerner Right, but I was thinking of using the DeclarationFinder to test whether there was a naming collision between 2 projects.
 
Ah, for that.
I think we should definetly avoid passing something that is too long for Application.Run to swallow.
 
10:54 PM
^
 
Is there actually anything we could do in case the document name was too long and there was a naming conflict without it?
 
I'm not entirely sure what to do in the failure case though - Run should probably return a bool so the TestEngine knows if a test was skipped, threw, failed, etc.
The Run calls need to be in try...catch blocks. We're just letting it bomb on COM errors now.
 
WTH did MS have to put in place these ridiculously small limits on everything?
Makes sense.
 
I think all of these interfaces were designed in like 1990.
 
Probably just a few years too early.
Even in Java you can have names milions of characters long, not that you would ever need that many.
 
11:02 PM
Yeah, that's taking the identifier thing a bit too far. "But the function name is the documentation".
public void ThisSubTakes2ParametersAndReturnsTheResultOfFrobbingTheFirstArgumentByTheRecipro‌​calOfTheSecondArgumentItIsTheCallersResponsibilityTo...
 
lol
 
But module names with more than 31 characters would be nice.
And running fully qualified procedured with more than 255 characters.
 
Wait it's the fully qualified name that has to be less than 255 chars?
 
What should we do when we catch a COMException from Applicatio.Run?
I just tested in Excel.
Application.Run throws whenever the string is longer than 255 characters.
 
Display it as Inconclusive - test name too long?
 
11:10 PM
In a module, every separator starts the count anew.
It might throw for another reason.
 
That's true. The length we can signal specifically.
We could still do something like Inconclusive - COM error.
 
^
We have a catch block in the tests anyway for things really coming from the test itself, right?
Well, unless somebody removes it.
 
> @Xipooo I think the only required annotation would be `@Interface` (already used to tell RD a class is an interface, when nothing implements it - when any class `Implements` it RD knows to treat it as an interface). What I'd love to do would be to `Setup` the mock, e.g.:

mock.Setup("GetFoo").Returns 42

The thing is that we're not hooked into the runtime, so we can't inject a VBA type from C#..it's like there's a wall between the VBA execution context and RD - being able to collect th
 
@M.Doerner Yep. In those cases we pass the error back via Assert.Fail.
@Duga Mocking user classes shouldn't be that hard - we'd just need to emit an object that matches the interface signature and pass that back from RD.
OK, for some values of "that hard".
 
@Duga Isn't it possible to inject VBA classes on runtime via import module?
 
11:18 PM
But we do have all of the information that we'd need to emit an object, new it up, and pass it back.
 
wait, we do??
 
In that case, we could emmit something akin to a cleaned up version of what I posted back then.
 
Yeah. We parse the user interfaces, any other interface that they would implement has to be imported in a reference.
I've never emitted a class from scratch though.
 
huh, and VBA would be happy with anything that matches the signatures??
 
Should be.
 
11:20 PM
that's totally feasible then!
 
That would obviously be some work; we would need some kind of class builder API.
 
It might have to be late bound, but I don't think it would be a problem.
 
Actually, we should be able to mock out nearly any user class, not only dedicated interfaces.
 
I might play around with the EasyHook library to see if it's possible to fake some common native calls like MsgBox and InputBox.
 
11:23 PM
The only exception I can see right now are those dreaded underscores.
 
Underscores?
 
Whenever there is an underscore in a public member name, the interface cannot be implemented.
The VBE determins the module portion of the name of the implementing method by looking for teh last underscore.
 
It can in .NET. I was thinking of Reflection.Emit and passing a managed object back into the running VBA code - not a VBA class or interface.
 
That should work then
 
That's different.
 
11:27 PM
just tested CallByName with a 255 character method name - works fine
 
but yeah, they can't have underscores
it's just a fact of life. no underscores.
 
@Mat'sMug can't underscore that enough
 
@M.Doerner Filename is 90 characters. It's within 4 folders on a mapped network drive.
 
I also tried setting the OnAction property of a shape - it too is seemingly capped at 255 chars
 
That does not really look like getting over 255 characters in total.
 
11:30 PM
Speaking of mocking, HTH do I test code that is checking the System.Type of a __ComObject?
 
Hm, I am not too sure whether we get the mapped name or the real full name of the network drive. (At work, those are really long.)
 
@Comintern the system.type of a __comobject is __comobject
 
@Comintern something like vbComponent.Property("Application").Object?
 
The Excel call should only be the filename without the path though.
 
Good question.
 
11:31 PM
So my issue is one that's been known about for a while it seems.
 
@IvenBach you should have a local dev copy ;-)
 
Right, but the methods under test take object as a parameter and then do things like this:
            var expectedType = expected.GetType();
            var actualType = actual.GetType();

            if (expectedType.IsArray && actualType.IsArray)
 
C:\Dev\VBA\MyProject\Foobar.xlsm
 
They have to take objects as parameters too.
 
@Mat'sMug Probably a good idea.
 
11:33 PM
The failing tests are ones like these:
        public void AreNotSameShouldFailWithSameReferences()
        {
            var assert = new AssertClass();
            var obj1 = new object();
            var obj2 = obj1;
            assert.AreNotSame(obj1, obj2);

            Assert.AreEqual(TestOutcome.Failed, _args.Outcome);
        }
 
🤔 "How do you do unit tests on a unit testing framework?" https://t.co/pib0RejG5K
 
@Mat'sMug The filename is the only part that matters though:
    var documentName = string.IsNullOrEmpty(module.ProjectPath)
        ? declaration.ProjectDisplayName
        : Path.GetFileName(module.ProjectPath);
 
I have just seen it as well.
Does string.Format call ToString on its arguments automatically?
 
yeah
 
Why does MS autotranslate its documentation? That is just plain annoying.
They even translate the keywords.
 
11:39 PM
to showcase Bing translate I suppose
 
@Mat'sMug If I find myself using the same syntax to create objects that should be an indication that I should have predeclareID set to true?
 
not necessarily
not at all actually
PredeclaredId makes VBA create a global-scope object variable named after the class, so if you have Class1 then you get a global object named Class1
and the last thing you want is state in that default instance
or did you mean a factory?
 
I'm pretty sure I'm not wanting the factory model.
My class that I'm using references a ListObject that houses Unique Id's for cell references and some information about that cell (If it has a formula, and where it's currently at).
 
@IvenBach Is the ListObject static?
 
I keep having to Dim someName as cClassName: set someName as new cClassName: someName.MethodToInitialize()
It just feels to me like there isn't the need to continually 'New up' the same variable, although I know I could be wrong.
 
11:48 PM
you could have a function whose job it is to create and return instances of cClassName given a ListObject parameter?
 
@Comintern The list object itself is in nearly every use is the same ListObject. There's only 1 or 2 exceptions.
 
if you're newing up the same variable over and over, you're definitely doing it wrong
 
^
 
That's what I was thinking.
 
11:49 PM
easy way to make application.Run work regardless of the filename is just set the project active, then Application.Run "ProcedureName". We could have a requirement that TestProcedureNames be unique across a project
 
Make the 1 or 2 exceptions parameters to the factory method.
 
I'm just trying to convert my inherited workbook and coerce it into something more maintainable.
 
@ThunderFrame that's quite a breaking change though
 
At your suggestion @Mat'sMug I eventually want to get rid of ListObject's entirely, but that's at some future point.
@Mat'sMug And this function itself would be part of a class or a standalone module?
 
@IvenBach Then keep that goal in mind when you're designing your interfaces.
 
11:51 PM
@Mat'sMug OK, so make requirement that testMethodName is unique OR moduleName + testMethodName must be less than 255 chars.
 
@Comintern I had a split second aha moment then lost it. Somethings picking at the back of my brain and that's generally a good thing when it comes to this stuff for me.
 
PermissiveAssertClass.RunTypePromotions needs to be an IEqualityComparer<object>. Why are the parameters ref parameters?
 
i.e. we can remove project name from the Application.Run argument. And we can make sure that a test that runs in a file called "BookWithShortName.xlsm" also runs in "BookWithReallyLongName.xlsm".
failing because the length of the file name changes is a bad outcome
 
00:00 - 19:0019:00 - 00:00

« first day (1011 days earlier)      last day (2169 days later) »