In the last email, I was considering a function that would do all the comparisons of the before and after values of the FieldChanges dictionary in the AuditEventDetails object and the Input dictionary I created. This would return a Boolean. It sounds good as I say it and it will reduce our super long Assert.IsTrue line to a simple function call.
I’m starting with this function I used to just compare 1 field. Now I want to just take the two dictionaries as arguments and compare the inputs with the results, looping through. Again, here is what I started with:
Private Function FieldBeforeIsSame(FieldName As String, dctInputs As Scripting.Dictionary, dctResults As Scripting.Dictionary) As Boolean
Dim retVal As Boolean
retVal = (dctResults(FieldName).OldValue = dctInputs(FieldName)(0))
FieldBeforeIsSame = retVal
End Function
First I’ll change the name of the function to something more sensible: FieldInputsMatchResults.
Private Function FieldInputsMatchResults(FieldName As String, dctInputs As Scripting.Dictionary, dctResults As Scripting.Dictionary) As Boolean
Dim retVal As Boolean
retVal = (dctResults(FieldName).OldValue = dctInputs(FieldName)(0))
FieldInputsMatchResults = retVal
End Function
Now, I will remove the first argument and just leave the two dictionaries:
Private Function FieldInputsMatchResults(dctInputs As Scripting.Dictionary, dctResults As Scripting.Dictionary) As Boolean
Dim retVal As Boolean
Dim FieldName As Variant
retVal = (dctResults(FieldName).OldValue = dctInputs(FieldName)(0))
FieldInputsMatchResults = retVal
End Function
In order to keep the code compiling, I Dim’med the FieldName variable in the function as a variant. And now to loop over dctInputs and make sure the expected results are in the dctResults.
Private Function FieldInputsMatchResults(dctInputs As Scripting.Dictionary, dctResults As Scripting.Dictionary) As Boolean
Dim retVal As Boolean
Dim FieldName As Variant, OldMatches As Boolean, NewMatches As Boolean
For Each FieldName In dctInputs
OldMatches = (dctResults(FieldName).OldValue = dctInputs(FieldName)(0))
NewMatches = (dctResults(FieldName).NewValue = dctInputs(FieldName)(1))
retVal = (OldMatches And NewMatches)
If retVal = False Then GoTo NoMoreMatchingNeeded
Next FieldName
NoMoreMatchingNeeded:
FieldInputsMatchResults = retVal
End Function
Not too bad. I’m looping, but at the first set that doesn’t fully match I set the retVal to false and end the loop.
I think this is still a bit heavy on lines and variable names, so I’m going to do another helper function to extract the old and new matches comparison. Here’s what I got:
Private Function FieldInputsMatchResults(dctInputs As Scripting.Dictionary, dctResults As Scripting.Dictionary) As Boolean
Dim retVal As Boolean
Dim FieldName As Variant
For Each FieldName In dctInputs
retVal = InputMatchesResult(CStr(FieldName), dctInputs, dctResults)
If retVal = False Then GoTo NoMoreMatchingNeeded
Next FieldName
NoMoreMatchingNeeded:
FieldInputsMatchResults = retVal
End Function
Private Function InputMatchesResult(FieldName As String, dctInputs As Scripting.Dictionary, dctResults As Scripting.Dictionary) As Boolean
Dim retVal As Boolean
Dim OldMatches As Boolean, NewMatches As Boolean
OldMatches = (dctResults(FieldName).OldValue = dctInputs(FieldName)(0))
NewMatches = (dctResults(FieldName).NewValue = dctInputs(FieldName)(1))
retVal = OldMatches And NewMatches
InputMatchesResult = retVal
End Function
I think overall that’s a bit cleaner and my functions are closer to doing just one thing. And finally I can finish off my Test function refactor like this. And I like this a lot more:
'@TestMethod("Verify Changes")
Private Sub WhenTwoTextFieldsChangeBeforeAndAfterValuesAreReturned()
Dim TestTextChange As AuditFieldChange, TestComboChange As AuditFieldChange
Dim dctInputs As New Scripting.Dictionary, dctResults As Scripting.Dictionary
dctInputs.Add "TestText", Array("TextBeforeValue", "TextAfterValue")
dctInputs.Add "TestCombo", Array("ComboBeforeValue", "ComboAfterValue")
Set dctResults = SetFields_ChangeThem_ReturnDictionary(dctInputs)
Assert.IsTrue FieldInputsMatchResults(dctInputs, dctResults)
End Sub
All right! Next time I will look at potentially using the new functions to rewrite the old tests if needed. I might be able to clean it up a bit more and make it super easy to write more tests.