-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Added tests for the BasicUnscrambler - Added a fixture for sharing the list of words between tests
- Loading branch information
Showing
5 changed files
with
171 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
using System.Diagnostics; | ||
using Xunit.Abstractions; | ||
|
||
namespace Unscrambler.Tests; | ||
|
||
[Collection("FindWords")] | ||
public class BasicUnscramblerTests | ||
{ | ||
private readonly ITestOutputHelper _output; | ||
private readonly WordListFixture _fixture; | ||
|
||
// Load words | ||
public BasicUnscramblerTests(ITestOutputHelper output, WordListFixture fixture) | ||
{ | ||
_output = output; | ||
_fixture = fixture; | ||
} | ||
|
||
[Theory] | ||
[InlineData("letters", 7)] | ||
[InlineData("resources", 10)] | ||
[InlineData("unscrambler", 12)] | ||
[InlineData("computer", 10)] | ||
[InlineData("programming", 6)] | ||
[InlineData("csharp", 4)] | ||
[InlineData("dotnet", 2)] | ||
[InlineData("visualstudio", 5)] | ||
[InlineData("test", 4)] | ||
|
||
public void CheckForWords(string letters, int maxLength) | ||
{ | ||
// Find all words using brute force | ||
var startTime = Stopwatch.GetTimestamp(); | ||
var checkList = _fixture.FindAllWordsUsingBruteForce(letters.ToCharArray(), maxLength); | ||
var bruteForceTimespan = Stopwatch.GetElapsedTime(startTime); | ||
|
||
// Find all words using the Unscrambler | ||
startTime = Stopwatch.GetTimestamp(); | ||
var unscrambled = _fixture._unscrambler.Unscramble(letters.ToCharArray(), maxLength); | ||
var unscrambleTimespan = Stopwatch.GetElapsedTime(startTime); | ||
|
||
// Output how long each method took | ||
|
||
_output.WriteLine($"Brute force took {bruteForceTimespan.TotalMicroseconds} us"); | ||
_output.WriteLine($"Unscramble took {unscrambleTimespan.TotalMicroseconds} us"); | ||
|
||
// Output how many times faster unscramble is than brute force | ||
_output.WriteLine($"Unscramble is {Math.Round(bruteForceTimespan.TotalMicroseconds / unscrambleTimespan.TotalMicroseconds, 3)} times faster than brute force"); | ||
|
||
// Check that the unscrambler found all the words | ||
Assert.Equal(checkList.Count, unscrambled.Count); | ||
|
||
foreach(var word in checkList) | ||
{ | ||
Assert.Contains(word, unscrambled); | ||
_output.WriteLine("Found: " + word); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
global using Xunit; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
|
||
<IsPackable>false</IsPackable> | ||
<IsTestProject>true</IsTestProject> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> | ||
<PackageReference Include="xunit" Version="2.6.6" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
<PackageReference Include="coverlet.collector" Version="6.0.0"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Unscrambler\Unscrambler.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
using Unscrambler.Basic; | ||
|
||
namespace Unscrambler.Tests | ||
{ | ||
[CollectionDefinition("FindWords")] | ||
public class FindWordsCollection : ICollectionFixture<WordListFixture> | ||
{ | ||
// This class has no code, and is never created. Its purpose is simply | ||
// to be the place to apply [CollectionDefinition] and all the | ||
// ICollectionFixture<> interfaces. | ||
} | ||
|
||
/// <summary> | ||
/// Use this class to load the word list and unscrambler once for all tests. This will speed up the tests.<br/> | ||
/// It also moves the code for loading words, from the test file to this fixture. | ||
/// </summary> | ||
public class WordListFixture | ||
{ | ||
// Url to the word list. You can update the word list by changing this url to a different word list, and removing the local file. | ||
public const string WordListUrl = "https://github.com/dolph/dictionary/raw/master/popular.txt"; | ||
// Path to the word list. This is where the word list will be downloaded to. | ||
public const string WordListPath = "popular.txt"; | ||
|
||
public readonly string[] _words; | ||
public readonly BasicUnscrambler _unscrambler = new(); | ||
|
||
public WordListFixture() | ||
{ | ||
// Check if the word list exists. If it doesn't, download it. | ||
if (!File.Exists(WordListPath)) | ||
{ | ||
using var client = new HttpClient(); | ||
var bytes = client.GetByteArrayAsync(WordListUrl).Result; | ||
File.WriteAllBytes(WordListPath, bytes); | ||
} | ||
|
||
_words = File.ReadAllLines(WordListPath); | ||
|
||
// Add words to unscrambler | ||
foreach (var word in _words) | ||
{ | ||
_unscrambler.AddWord(word); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Finds all words using brute force. | ||
/// </summary> | ||
public HashSet<string> FindAllWordsUsingBruteForce(char[] letters, int maxLength) | ||
{ | ||
var words = new HashSet<string>(100); | ||
foreach (var word in _words) | ||
{ | ||
if (word.Length > maxLength) | ||
{ | ||
continue; | ||
} | ||
var lettersCopy = letters.ToList(); | ||
var isMatch = true; | ||
foreach (var letter in word) | ||
{ | ||
if (!lettersCopy.Remove(letter)) | ||
{ | ||
isMatch = false; | ||
break; | ||
} | ||
} | ||
if (isMatch) | ||
{ | ||
words.Add(word); | ||
} | ||
} | ||
return words; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters