mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-28 21:54:17 -08:00
Added tests project
This commit is contained in:
@@ -3,12 +3,12 @@
|
||||
<PropertyGroup>
|
||||
<RootNamespace>Animal.Tests</RootNamespace>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<OptionStrict>On</OptionStrict>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
@@ -20,4 +20,8 @@
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Animal\Animal.vbproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
65
03_Animal/vbnet/Animal.Tests/MockConsole.vb
Normal file
65
03_Animal/vbnet/Animal.Tests/MockConsole.vb
Normal file
@@ -0,0 +1,65 @@
|
||||
Imports System.IO
|
||||
|
||||
Public Class MockConsole
|
||||
Inherits ConsoleAdapterBase
|
||||
|
||||
Private inputs As Queue(Of String)
|
||||
Public ReadOnly Lines As New List(Of (line As String, centered As Boolean)) From {
|
||||
("", False)
|
||||
}
|
||||
|
||||
' TODO it's possible to clear all the lines, and we'd have to check once again in WriteString and WriteCenteredLine if there are any lines
|
||||
|
||||
Sub New(Inputs As IEnumerable(Of String))
|
||||
Me.inputs = New Queue(Of String)(Inputs)
|
||||
End Sub
|
||||
|
||||
Private Sub CheckLinesInitialized()
|
||||
If Lines.Count = 0 Then Lines.Add(("", False))
|
||||
End Sub
|
||||
|
||||
Private Sub WriteString(s As String, Optional centered As Boolean = False)
|
||||
If s Is Nothing Then Return
|
||||
CheckLinesInitialized()
|
||||
s.Split(Environment.NewLine).ForEach(Sub(line, index)
|
||||
If index = 0 Then
|
||||
Dim currentLast = Lines(Lines.Count - 1)
|
||||
' centered should never come from the current last line
|
||||
' if WriteCenteredLine is called, it immediately creates a new line
|
||||
Lines(Lines.Count - 1) = (currentLast.line + line, centered)
|
||||
Else
|
||||
Lines.Add((line, centered))
|
||||
End If
|
||||
End Sub)
|
||||
End Sub
|
||||
|
||||
Public Overrides Sub Write(value As Object)
|
||||
WriteString(value?.ToString)
|
||||
End Sub
|
||||
|
||||
Public Overrides Sub WriteLine(value As Object)
|
||||
WriteString(value?.ToString)
|
||||
WriteLine()
|
||||
End Sub
|
||||
|
||||
Public Overrides Sub WriteLine()
|
||||
Lines.Add(("", False))
|
||||
End Sub
|
||||
|
||||
Public Overrides Sub WriteCenteredLine(value As Object)
|
||||
If Lines.Count = 0 Then Lines.Add(("", False))
|
||||
Dim currentLast = Lines(Lines.Count - 1).line
|
||||
If currentLast.Length > 0 Then Throw New InvalidOperationException("Can only write centered line if cursor is at start of line.")
|
||||
WriteString(value?.ToString, True)
|
||||
WriteLine()
|
||||
End Sub
|
||||
|
||||
Public Overrides Function ReadLine() As String
|
||||
' Indicates the end of a test run, for programs which loop endlessly
|
||||
If inputs.Count = 0 Then Throw New EndOfStreamException("End of inputs")
|
||||
|
||||
Dim nextInput = inputs.Dequeue.Trim
|
||||
WriteLine(nextInput)
|
||||
Return nextInput
|
||||
End Function
|
||||
End Class
|
||||
80
03_Animal/vbnet/Animal.Tests/TestContainer.vb
Normal file
80
03_Animal/vbnet/Animal.Tests/TestContainer.vb
Normal file
@@ -0,0 +1,80 @@
|
||||
Imports Xunit
|
||||
Imports Animal
|
||||
Imports System.IO
|
||||
|
||||
Public Class TestContainer
|
||||
Private Shared Function ResponseVariantExpander(src As IEnumerable(Of String)) As TheoryData(Of String)
|
||||
Dim theoryData = New TheoryData(Of String)
|
||||
src.
|
||||
SelectMany(Function(x) {x, x.Substring(0, 1)}).
|
||||
SelectMany(Function(x) {
|
||||
x,
|
||||
x.ToUpperInvariant,
|
||||
x.ToLowerInvariant,
|
||||
x.ToTitleCase,
|
||||
x.ToReverseCase
|
||||
}).
|
||||
Distinct.
|
||||
ForEach(Sub(x) theoryData.Add(x))
|
||||
Return theoryData
|
||||
End Function
|
||||
Private Shared YesVariantsThepryData As TheoryData(Of String) = ResponseVariantExpander({"yes", "true", "1"})
|
||||
Private Shared Function YesVariants() As TheoryData(Of String)
|
||||
Return YesVariantsThepryData
|
||||
End Function
|
||||
Private Shared NoVariantsThepryData As TheoryData(Of String) = ResponseVariantExpander({"no", "false", "0"})
|
||||
Private Shared Function NoVariants() As TheoryData(Of String)
|
||||
Return NoVariantsThepryData
|
||||
End Function
|
||||
|
||||
''' <summary>Test LIST variants</summary>
|
||||
<Theory>
|
||||
<InlineData("LIST")>
|
||||
<InlineData("list")>
|
||||
<InlineData("List")>
|
||||
<InlineData("lIST")>
|
||||
Sub List(listResponse As String)
|
||||
Dim console As New MockConsole({listResponse})
|
||||
Dim game As New Game(console)
|
||||
Assert.Throws(Of EndOfStreamException)(Sub() game.BeginLoop())
|
||||
Assert.Equal(
|
||||
{
|
||||
"ANIMALS I ALREADY KNOW ARE:",
|
||||
"FISH BIRD "
|
||||
},
|
||||
console.Lines.Slice(-4, -2).Select(Function(x) x.line)
|
||||
)
|
||||
End Sub
|
||||
|
||||
'' <summary>Test YES variants</summary>
|
||||
<Theory>
|
||||
<MemberData(NameOf(YesVariants))>
|
||||
Sub YesVariant(yesVariant As String)
|
||||
Dim console As New MockConsole({yesVariant})
|
||||
Dim game As New Game(console)
|
||||
Assert.Throws(Of EndOfStreamException)(Sub() game.BeginLoop())
|
||||
Assert.Equal(
|
||||
{
|
||||
$"ARE YOU THINKING OF AN ANIMAL? {yesVariant}",
|
||||
"DOES IT SWIM? "
|
||||
},
|
||||
console.Lines.Slice(-2, 0).Select(Function(x) x.line)
|
||||
)
|
||||
End Sub
|
||||
|
||||
'' <summary>Test NO variants</summary>
|
||||
<Theory>
|
||||
<MemberData(NameOf(NoVariants))>
|
||||
Sub NoVariant(noVariant As String)
|
||||
Dim console As New MockConsole({"y", noVariant})
|
||||
Dim game As New Game(console)
|
||||
Assert.Throws(Of EndOfStreamException)(Sub() game.BeginLoop())
|
||||
Assert.Equal(
|
||||
{
|
||||
$"DOES IT SWIM? {noVariant}",
|
||||
"IS IT A BIRD? "
|
||||
},
|
||||
console.Lines.Slice(-2, 0).Select(Function(x) x.line)
|
||||
)
|
||||
End Sub
|
||||
End Class
|
||||
@@ -1,12 +0,0 @@
|
||||
Imports System
|
||||
Imports Xunit
|
||||
|
||||
Namespace Animal.Tests
|
||||
Public Class UnitTest1
|
||||
<Fact>
|
||||
Sub TestSub()
|
||||
|
||||
End Sub
|
||||
End Class
|
||||
End Namespace
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
End Sub
|
||||
|
||||
Public Overrides Sub WriteCenteredLine(value As Object)
|
||||
If Console.CursorLeft <> 0 Then Throw New InvalidOperationException("Can only write centered line if cursor is at start of line.")
|
||||
Dim toWrite = If(value?.ToString, "")
|
||||
Console.WriteLine($"{Space((Console.WindowWidth - toWrite.Length) \ 2)}{toWrite}")
|
||||
End Sub
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
Imports System.Runtime.CompilerServices
|
||||
|
||||
Public Module Extensions
|
||||
<Extension> Public Sub ForEach(Of T)(src As IEnumerable(Of T), action As Action(Of T))
|
||||
For Each x In src
|
||||
action(x)
|
||||
Next
|
||||
End Sub
|
||||
<Extension> Public Sub ForEach(Of T)(src As IEnumerable(Of T), action As Action(Of T, Integer))
|
||||
Dim index As Integer
|
||||
For Each x In src
|
||||
@@ -18,4 +23,28 @@ Public Module Extensions
|
||||
If Not s.EndsWith(toAppend, StringComparison.OrdinalIgnoreCase) Then s += toAppend
|
||||
Return s
|
||||
End Function
|
||||
|
||||
<Extension> Public Function ToTitleCase(s As String) As String
|
||||
If s Is Nothing Then Return Nothing
|
||||
Return Char.ToUpperInvariant(s(0)) + s.Substring(1).ToUpperInvariant
|
||||
End Function
|
||||
|
||||
' https://stackoverflow.com/a/3681580/111794
|
||||
<Extension> Public Function ToReverseCase(s As String) As String
|
||||
If s Is Nothing Then Return Nothing
|
||||
Return New String(s.Select(Function(c) If(
|
||||
Not Char.IsLetter(c),
|
||||
c,
|
||||
If(
|
||||
Char.IsUpper(c), Char.ToLowerInvariant(c), Char.ToUpperInvariant(c)
|
||||
)
|
||||
)).ToArray)
|
||||
End Function
|
||||
|
||||
' https://stackoverflow.com/a/58132204/111794
|
||||
<Extension> Public Function Slice(Of T)(lst As IList(Of T), start As Integer, [end] As Integer) As T()
|
||||
start = If(start >= 0, start, lst.Count + start)
|
||||
[end] = If([end] > 0, [end], lst.Count + [end])
|
||||
Return lst.Skip(start).Take([end] - start).ToArray
|
||||
End Function
|
||||
End Module
|
||||
|
||||
Reference in New Issue
Block a user