Skip to content

Commit

Permalink
Unit test cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
jas88 committed Mar 14, 2023
1 parent ec596e7 commit b3ae244
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 137 deletions.
2 changes: 1 addition & 1 deletion Application/ResearchDataManagementPlatform/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ static void Main(string[] args)
}
catch (Exception)
{
Console.WriteLine("Couldn't redirect console. Nevermind");
Console.WriteLine("Couldn't redirect console. Never mind");
}

Startup.PreStartup();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,6 @@ public void f_invalid_target_field_evokes_exception()
}

[Test]
[Ignore("Thomas, can you fix please?")]
public void f_invalid_comparator_field_evokes_exception()
{
var v = new Validator();
Expand Down
2 changes: 1 addition & 1 deletion Rdmp.Core/Validation/ItemValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ private ValidationFailure ValidateSecondayConstraints(object columnValue, object
}
catch (Exception ex)
{
throw new Exception($"Error processing Secondary Constraint validator of Type {secondaryConstraint.GetType().Name} on column {TargetProperty}. Value being validated was '{columnValue}'",ex);
throw new InvalidOperationException($"Error processing Secondary Constraint validator of Type {secondaryConstraint.GetType().Name} on column {TargetProperty}. Value being validated was '{columnValue}'",ex);
}
}

Expand Down
25 changes: 12 additions & 13 deletions Rdmp.Core/Validation/Validator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -351,20 +351,19 @@ private ValidationFailure ValidateAgainstDictionary()
if (_domainObjectDictionary.TryGetValue(itemValidator.TargetProperty, out o))
{
//get the first validation failure for the given column (or null if it is valid)
ValidationFailure result = itemValidator.ValidateAll(o, vals, keys);
var result = itemValidator.ValidateAll(o, vals, keys);

//if it wasn't valid then add it to the eList
if(result != null)
if (result.SourceItemValidator == null)
{
result.SourceItemValidator = itemValidator;
eList.Add(result);
}
if(result is { SourceItemValidator: null })
{
result.SourceItemValidator = itemValidator;
eList.Add(result);
}
}
else
{
throw new InvalidOperationException("Validation failed: Target field [" + itemValidator.TargetProperty +
"] not found in dictionary.");
throw new InvalidOperationException(
$"Validation failed: Target field [{itemValidator.TargetProperty}] not found in dictionary.");
}
}

Expand Down Expand Up @@ -460,9 +459,8 @@ private ValidationFailure ValidateAgainstDomainObject()
result = itemValidator.ValidateAll(value, propertiesDictionary.Values.ToArray(), propertiesDictionary.Keys.ToArray());
}
else
throw new MissingFieldException("Validation failed: Target field [" +
itemValidator.TargetProperty +
"] not found in domain object.");
throw new MissingFieldException(
$"Validation failed: Target field [{itemValidator.TargetProperty}] not found in domain object.");

}
if (result != null)
Expand All @@ -475,7 +473,8 @@ private ValidationFailure ValidateAgainstDomainObject()
}
catch (IndexOutOfRangeException)
{
throw new IndexOutOfRangeException("Validation failed: Target field [" + itemValidator.TargetProperty + "] not found in domain object.");
throw new IndexOutOfRangeException(
$"Validation failed: Target field [{itemValidator.TargetProperty}] not found in domain object.");
}
}

Expand Down
34 changes: 10 additions & 24 deletions Rdmp.UI.Tests/DesignPatternTests/AllObjectsHaveImages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@ public class AllObjectsHaveImages:DatabaseTests
[Test]
public void AllIHasDependenciesHaveIcons()
{
List<string> missingConcepts = new List<string>();


string[] ExceptionsAllowed = new[]
string[] exceptionsAllowed = new[]
{

"IHasDependencies", //base interface of which nobody is who isn't otherwise on this list
Expand All @@ -40,27 +37,16 @@ public void AllIHasDependenciesHaveIcons()

};

foreach (Type type in RepositoryLocator.CatalogueRepository.MEF.GetAllTypes().Where(t => typeof (IHasDependencies).IsAssignableFrom(t) && !t.IsInterface))
{
//skip masqueraders
if(typeof(IMasqueradeAs).IsAssignableFrom(type))
continue;

var typeName = type.Name;
if (ExceptionsAllowed.Any(s=>s.Equals(typeName)))
continue;

try
{
var c = Enum.Parse(typeof (RDMPConcept), typeName);
}
catch (Exception)
{
missingConcepts.Add(typeName);
}
}
var missingConcepts = RepositoryLocator.CatalogueRepository.MEF.GetAllTypes()
.Where(t => typeof(IHasDependencies).IsAssignableFrom(t) && !t.IsInterface)
.Where(type => !typeof(IMasqueradeAs).IsAssignableFrom(type))
.Select(type => type.Name)
.Where(typeName => !exceptionsAllowed.Any(s => s.Equals(typeName)))
.Where(typeName => !Enum.TryParse(typeof(RDMPConcept), typeName, out _)).ToList();

Console.WriteLine("The following Database Object Types are missing concepts (and therefore images) in CatalogueManager.exe" + Environment.NewLine + string.Join("," + Environment.NewLine , missingConcepts));
if (missingConcepts.Count > 0)
Console.WriteLine(
$"The following Database Object Types are missing concepts (and therefore images) in CatalogueManager.exe{Environment.NewLine}{string.Join($",{Environment.NewLine}", missingConcepts)}");

Assert.AreEqual(0,missingConcepts.Count);
}
Expand Down
11 changes: 3 additions & 8 deletions Rdmp.UI.Tests/DesignPatternTests/AllUIsDocumentedTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ namespace Rdmp.UI.Tests.DesignPatternTests
{
public class AllUIsDocumentedTest : UnitTests
{
private int evaluatedClasses = 0;

[Test]
public void EveryClassInAppropriateNamespace()
{
Expand Down Expand Up @@ -78,17 +76,14 @@ private IEnumerable<string> EnforceTypeBelongsInNamespace(Type InterfaceType, pa
if (type.Namespace.Contains(".Tests"))
continue;

//theese guys can be wherever they want
//these guys can be wherever they want
if (_exemptNamespaces.Any(e => type.Namespace.Contains(e)))
continue;

if (!legalNamespaces.Any(ns=>type.Namespace.Contains(ns)))
yield return "Expected Type '" + type.Name + "' to be in namespace(s) '" + string.Join("' or '",legalNamespaces) + "' but it was in '" + type.Namespace + "'";

evaluatedClasses++;
yield return
$"Expected Type '{type.Name}' to be in namespace(s) '{string.Join("' or '", legalNamespaces)}' but it was in '{type.Namespace}'";
}

Console.WriteLine("Evaluated " + evaluatedClasses + " classes for namespace compatibility");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -350,44 +350,26 @@ public void FindProblems(List<string> csFilesFound)
}


foreach (KeyValuePair<string, HashSet<string>> kvp in fileCommentTokens)
foreach (var (filename,tokens) in fileCommentTokens)
{
foreach (string s in kvp.Value)
{
if(!codeTokens.Contains(s) && !codeTokens.Contains($"ExecuteCommand{s}"))
{
if (IgnoreList.Contains(s))
continue;

//it's SHOUTY TEXT
if (s.ToUpper() == s)
continue;

//if it's a plural e.g. TableInfos then we are still ok if we find TableInfo
if (s.Length > 2 && s.EndsWith("s"))
{
if (codeTokens.Contains(s.Substring(0, s.Length - 1)))
continue;
}

problems.Add(
$"FATAL PROBLEM: File '{kvp.Key}' talks about something which isn't in the codebase, called a:{Environment.NewLine}{s}");

}
}
problems.AddRange(tokens
.Where(token => !codeTokens.Contains(token) && !codeTokens.Contains($"ExecuteCommand{token}"))
.Where(token => !IgnoreList.Contains(token))
.Where(token => token.ToUpper() != token)
.Where(token => token.Length <= 2 || !token.EndsWith("s") || !codeTokens.Contains(token[..^1]))
.Select(token =>
$"FATAL PROBLEM: File '{filename}' talks about something which isn't in the codebase, called a:{Environment.NewLine}{token}"));
}

if (problems.Any())
{
Console.WriteLine("Found problem words in comments (Scroll down to see by file then if you think they are fine add them to DocumentationCrossExaminationTest._ignorelist):");
foreach (var pLine in problems.Where(l=>l.Contains('\n')).Select(p => p.Split('\n')))
Console.WriteLine($"\"{pLine[1]}\",");

foreach (string problem in problems)
Console.WriteLine(problem);
}

foreach (string problem in problems)
Console.WriteLine(problem);

Assert.AreEqual(0,problems.Count,"Expected there to be nothing talked about in comments that doesn't appear in the codebase somewhere");
}

Expand Down Expand Up @@ -448,11 +430,7 @@ private void EnsureCodeBlocksCompile(string mdFile, List<string> problems)

Assert.AreEqual(code.Trim(), docs.Trim(),
$"Code in the documentation markdown (actual) did not match the corresponding compiled code (expected) for code guid {kvp.Key} markdown file was {mdFile} and code file was {codeBlocks}");

Console.WriteLine($"Validated markdown block {kvp.Key}");
}

Console.WriteLine($"Validated {markdownCodeBlocks.Count} markdown blocks");
}

private void EnsureMaximumGlossaryUse(string mdFile, List<string> problems)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,16 @@ public class RDMPFormInitializationTests

public void FindUninitializedForms(List<string> csFiles )
{
foreach (string file in csFiles)
foreach (var readToEnd in csFiles.Select(File.ReadAllText))
{
var readToEnd = File.ReadAllText(file);
DealWithRDMPForms(readToEnd);
DealWithRDMPUserControls(readToEnd);
}

List<string> rdmpFormClassNames = _rdmpFormClassNames;
var rdmpFormClassNames = _rdmpFormClassNames;

//look for "new (myclass1|myclass2)\s*\("
StringBuilder sbFindInstantiations = new StringBuilder();
var sbFindInstantiations = new StringBuilder();
sbFindInstantiations.Append("new (");
sbFindInstantiations.Append(string.Join("|", rdmpFormClassNames.Select(Regex.Escape)));
sbFindInstantiations.Append(")\\s*\\(");
Expand All @@ -56,46 +55,36 @@ public void FindUninitializedForms(List<string> csFiles )
private void DealWithRDMPUserControls(string readToEnd)
{
var match = rdmpControlClasses.Match(readToEnd);
if (match.Success)
{
string className = match.Groups[1].Value.Trim();
Console.WriteLine("Class " + className + " is an RDMPUSerControl");

ComplainIfUsesVisualStudioDesignerDetectionMagic(readToEnd);
ComplainIfAccessesRepositoryLocatorInConstructor(readToEnd, className);

}
if (!match.Success) return;
var className = match.Groups[1].Value.Trim();
ComplainIfUsesVisualStudioDesignerDetectionMagic(readToEnd);
ComplainIfAccessesRepositoryLocatorInConstructor(readToEnd, className);
}

private void DealWithRDMPForms(string readToEnd)
{
var match = rdmpFormClasses.Match(readToEnd);
if (match.Success)
{
string className = match.Groups[1].Value.Trim();
Console.WriteLine("Class " + className + " is an RDMPForm");

_rdmpFormClassNames.Add(className);

ComplainIfUsesVisualStudioDesignerDetectionMagic(readToEnd);
ComplainIfAccessesRepositoryLocatorInConstructor(readToEnd, className);
}
if (!match.Success) return;
var className = match.Groups[1].Value.Trim();
_rdmpFormClassNames.Add(className);
ComplainIfUsesVisualStudioDesignerDetectionMagic(readToEnd);
ComplainIfAccessesRepositoryLocatorInConstructor(readToEnd, className);
}

private void ComplainIfAccessesRepositoryLocatorInConstructor(string readToEnd, string className)
{
//find constructor
Regex constructorRegex = GetConstructoRegex(className);
var constructorRegex = GetConstructorRegex(className);

var matchConstructor = constructorRegex.Match(readToEnd);
if (matchConstructor.Success)
{
int curlyBracerCount = -1;
int index = 0;
var curlyBracerCount = -1;
var index = 0;

string substring = readToEnd.Substring(matchConstructor.Index);
var substring = readToEnd[matchConstructor.Index..];

StringBuilder sbConstructor = new StringBuilder();
var sbConstructor = new StringBuilder();
while (curlyBracerCount != 0 && index < substring.Length)
{
if (substring[index] == '{')
Expand All @@ -116,45 +105,26 @@ private void ComplainIfAccessesRepositoryLocatorInConstructor(string readToEnd,

var constructor = sbConstructor.ToString();

//find other method the constructor calls
foreach (Match m in methodCalls.Matches(constructor))
{
string methodName = m.Groups[1].Value;

if (methodIgnoreList.Contains(methodName))
continue;

Console.WriteLine("Constructor calls method:" + m.Groups[1].Value);
}


if (Regex.IsMatch(constructor,"[^.]RepositoryLocator") || constructor.Contains("_repositoryLocator"))
Assert.Fail("Constructor of class " + className +
" contains a reference to RepositoryLocator, this property cannot be used until OnLoad is called");
Assert.Fail(
$"Constructor of class {className} contains a reference to RepositoryLocator, this property cannot be used until OnLoad is called");
}
else
{
Console.WriteLine("Class " + className + " is an RDMPForm/RDMPUserControl but doesn't have a constructor!");
Console.WriteLine($"Class {className} is an RDMPForm/RDMPUserControl but doesn't have a constructor!");
}
}

private void ComplainIfUsesVisualStudioDesignerDetectionMagic(string readToEnd)
{
if (readToEnd.Contains("LicenseManager.UsageMode"))
{
int lineNumber = readToEnd.Substring(0, readToEnd.IndexOf("LicenseManager.UsageMode")).Count(c => c == '\n');
if (!readToEnd.Contains("LicenseManager.UsageMode")) return;
var lineNumber = readToEnd[..readToEnd.IndexOf("LicenseManager.UsageMode")].Count(c => c == '\n');

string msg =
"FAIL: Use protected variable VisualStudioDesignMode instead of LicenseManager.UsageMode (line number:" +
lineNumber + ")";
Console.WriteLine(msg);
_fails.Add(msg);
}
}
private Regex GetConstructoRegex(string className)
{
return new Regex("(public|private)\\s+" + className + "\\s*\\(.*\\{", RegexOptions.Singleline);
var msg =
$"FAIL: Use protected variable VisualStudioDesignMode instead of LicenseManager.UsageMode (line number:{lineNumber})";
Console.WriteLine(msg);
_fails.Add(msg);
}

private static Regex GetConstructorRegex(string className) => new Regex($"(public|private)\\s+{className}\\s*\\(.*\\{{", RegexOptions.Singleline);
}
}

0 comments on commit b3ae244

Please sign in to comment.