Skip to content

Commit

Permalink
✅ test(add job test): add tests for the add job cmd
Browse files Browse the repository at this point in the history
update job and resumeContext class for tests.
Add updated check in qodana analysis

Signed-off-by: csc530 <[email protected]>
  • Loading branch information
csc530 committed Dec 18, 2023
1 parent 4edfad1 commit 83dd806
Show file tree
Hide file tree
Showing 15 changed files with 340 additions and 91 deletions.
7 changes: 7 additions & 0 deletions .idea/.idea.resume builder/.idea/dataSources.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions .run/resume builder add job.run.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="resume builder add job" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="$PROJECT_DIR$/resume builder/bin/Debug/net7.0/resume builder" />
<option name="EXE_PATH" value="$PROJECT_DIR$/resume builder/bin/Release/net8.0/resume builder.exe"/>
<option name="PROGRAM_PARAMETERS" value="add job --start 2023.12.10 --title freelance -c walmart" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/resume builder/bin/Debug/net7.0" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/resume builder/bin/Release/net8.0"/>
<option name="PASS_PARENT_ENVS" value="1" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="USE_MONO" value="0" />
Expand All @@ -12,7 +12,7 @@
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value="net7.0" />
<option name="PROJECT_TFM" value="net8.0"/>
<method v="2">
<option name="Build" />
</method>
Expand Down
26 changes: 0 additions & 26 deletions TestResumeBuilder/AppTestBase.cs

This file was deleted.

55 changes: 55 additions & 0 deletions TestResumeBuilder/TestBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using resume_builder;
using resume_builder.models;
using Spectre.Console.Testing;

namespace TestResumeBuilder
{

Check notice on line 6 in TestResumeBuilder/TestBase.cs

View workflow job for this annotation

GitHub Actions / qodana

Use preferred namespace body style

Convert to file-scoped namespace
//todo: find way to pass text to test command app for prompts
public abstract class TestBase: IDisposable, IAsyncDisposable
{
internal CommandAppTester TestApp;
internal ResumeContext TestDb;

public TestBase()
{
//given
TestApp = new CommandAppTester();
TestApp.Configure(Program.AppConfiguration);
TestDb = new ResumeContext();
}

public async ValueTask DisposeAsync()
{
TestDb.Jobs.RemoveRange(TestDb.Jobs);
TestDb.Projects.RemoveRange(TestDb.Projects);
TestDb.Profiles.RemoveRange(TestDb.Profiles);
TestDb.Companies.RemoveRange(TestDb.Companies);
TestDb.Skills.RemoveRange(TestDb.Skills);
await TestDb.SaveChangesAsync();
await TestDb.DisposeAsync();
GC.SuppressFinalize(this);
}

public void Dispose()
{
TestDb.Jobs.RemoveRange(TestDb.Jobs);
TestDb.Projects.RemoveRange(TestDb.Projects);
TestDb.Profiles.RemoveRange(TestDb.Profiles);
TestDb.Companies.RemoveRange(TestDb.Companies);
TestDb.Skills.RemoveRange(TestDb.Skills);
TestDb.SaveChanges();
TestDb.Dispose();

GC.SuppressFinalize(this);
}

protected CommandAppResult Run(IEnumerable<string> cmdArgs, params string[] args) =>
TestApp.Run(cmdArgs.Concat(args).ToArray());

protected CommandAppResult Run(string cmd, params string[] args) =>
Run(args.Prepend(cmd));

protected CommandAppFailure RunAndCatch<T>(IEnumerable<string> cmdArgs, params string[] args)
where T : Exception => TestApp.RunAndCatch<T>(cmdArgs.Concat(args).ToArray());
}
}
14 changes: 0 additions & 14 deletions TestResumeBuilder/TestData.cs

This file was deleted.

1 change: 1 addition & 0 deletions TestResumeBuilder/TestResumeBuilder.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Spectre.Console.Testing" Version="0.48.0" />
<PackageReference Include="WaffleGenerator" Version="4.2.1"/>
<PackageReference Include="xunit" Version="2.6.3" />
<PackageReference Include="xunit.analyzers" Version="1.7.0">
<PrivateAssets>all</PrivateAssets>
Expand Down
21 changes: 13 additions & 8 deletions TestResumeBuilder/commands/InitTest.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
using resume_builder.models;

namespace TestResumeBuilder.commands;

public class InitTest : AppTestBase
public class InitTest: TestBase
{
[Fact]
public void Init_WithNoArgs_ShouldReturnSuccess()
{
//when
var result = TestApp.Run("init");
//then
Assert.Equal(0, result.ExitCode);
}


[Theory]
[MemberData(nameof(TestData.RandomArgs), MemberType = typeof(TestData))]
public void Init_WithArgs_ShouldReturnSuccess(string[] args)
[Fact]
public void Init_WithNoArgs_ShouldCreateDb()
{
Assert.True(true);
//var result = Run("init", args);
//Assert.That(result.ExitCode, Is.EqualTo(0));
//when
var result = TestApp.Run("init");
//then
Assert.True(File.Exists("TestResumeBuilder.db"));
Assert.Equal(0, result.ExitCode);
TestDb = new ResumeContext();
Assert.True(TestDb.Database.CanConnect());
}
}
132 changes: 132 additions & 0 deletions TestResumeBuilder/commands/add/AddJobTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using Bogus;
using resume_builder;
using resume_builder.cli.commands.add;
using resume_builder.models;

namespace TestResumeBuilder.commands.add;

public class AddJobTest: TestBase
{
static readonly string[] cmdArgs = ["add", "job"];

public static readonly TheoryData<string, string, DateOnly, string?, string?, DateOnly?> AddJobData =
new()
{
{
"jobTitle", "companyName", new DateOnly(2021, 1, 1), "jobDescription", "experience",
new DateOnly(2231, 1, 1)
}
};

[Fact(Skip =
"hangs forever (at least in vs2022) because it's expecting input in interactive mode which can't be emulated right now with its (spectre) test console")]
public void AddJob_WithNoArgs_ShouldFail()
{
//this hangs forever becuase a prompt is required
//and I have no idea how to inject a response to the app
//I added a timeout so it sould stop
var result = TestApp.Run(cmdArgs);
Assert.Equal(ExitCode.Error.ToInt(), result.ExitCode);
}

[Theory]
[MemberData(nameof(AddJobTestData.JobTitleAndStartDate), MemberType = typeof(AddJobTestData))]
public void AddJob_WithNameAndStartOptions_ShouldSucceed(string jobTitle, string companyName, DateOnly startDate)
{
//when
var result = TestApp.Run([.. cmdArgs, "-t", jobTitle, "-s", startDate.ToString(), "-c", companyName]);
var resultSettings = result.Settings as AddJobSettings;
//then
Assert.Multiple(() =>
{
Assert.Equal(0, result.ExitCode);
Assert.NotNull(resultSettings);
Assert.Equal(jobTitle, resultSettings.JobTitle);
Assert.Equal(companyName, resultSettings.Company);
Assert.Equal(startDate, resultSettings.StartDate);
});
}

[Theory]
[MemberData(nameof(AddJobTestData.AllOptions), MemberType = typeof(AddJobTestData))]
public void AddJob_WithAllOptions_ShouldSucceed(string jobTitle, string companyName, DateOnly startDate,
string? jobDescription, string? experience, DateOnly? endDate)
{
//? job description and experience are non-null because in the run it will be parsed/replaced with an empty string
// and users can't enter the null value
//which is to say they can choose to enter nothing with empty quotes which this test tests for too
//when
string[]? descriptionArg = jobDescription == null ? [null] : ["-d", $"{jobDescription}"];
string[]? expArg = experience == null ? [null] : ["-x", $"{experience}"];
string[]? endArg = endDate == null ? [null] : ["-e", $"{endDate}"];
List<string?> args =
[
..cmdArgs, ..descriptionArg, ..expArg, ..endArg, "-t", jobTitle, "-s", startDate.ToString(), "-c",
companyName
];
var result = Run(args.Where(x => x != null).ToArray()!);
var resultSettings = result.Settings as AddJobSettings;
//then
Assert.Equal(0, result.ExitCode);
Assert.NotNull(resultSettings);
Assert.Equal(jobTitle, resultSettings.JobTitle);
Assert.Equal(companyName, resultSettings.Company);
Assert.Equal(startDate, resultSettings.StartDate);
Assert.Equal(jobDescription, resultSettings.JobDescription);
Assert.Equal(experience, resultSettings.Experience);
Assert.Equal(endDate, resultSettings.EndDate);
}

[Theory]
[MemberData(nameof(AddJobData))]
[MemberData(nameof(AddJobTestData.AllOptions), MemberType = typeof(AddJobTestData))]
public void AddJob_WithAllOptions_ShouldUpdateDB(string jobTitle, string companyName, DateOnly startDate,
string? jobDescription, string? experience, DateOnly? endDate)
{
string[] descriptionArg = jobDescription == null ? [null] : [$"-d", $"{jobDescription}"];
string[] expArg = experience == null ? [null] : [$"-x", $"{experience}"];
string[] endArg = endDate == null ? [null] : [$"-e", $"{endDate}"];
string?[] args =
[
..cmdArgs, "-t", jobTitle, "-s", startDate.ToString(), "-c", companyName, ..descriptionArg, ..expArg,
..endArg
];
var result = TestApp.Run(args.Where(x => x != null).ToArray()!);
Assert.Equal(0, result.ExitCode);
var job = TestDb.Jobs.First(j => j.Title == jobTitle && j.Company == companyName && j.StartDate == startDate);
Assert.NotNull(job);
//clean inputs; trim and nullify empty strings
jobDescription = jobDescription?.Trim();
companyName = companyName.Trim();
experience = experience?.Trim();
jobTitle = jobTitle.Trim();


Assert.Equal(jobTitle, job!.Title);
Assert.Equal(companyName, job.Company);
Assert.Equal(startDate, job.StartDate);
Assert.Equal(jobDescription.IsBlank() ? null : jobDescription, job.Description);
Assert.Equal(experience.IsBlank() ? null : experience, job.Experience);
Assert.Equal(endDate, job.EndDate);
}
}

internal class AddJobTestData: JobTestData
{
public static TheoryData<string, string, DateOnly> JobTitleAndStartDate()
{
var data = new TheoryData<string, string, DateOnly>();
for(var i = TestRepetitions - 1; i >= 0; i--)
data.Add(RandomJobTitle(), RandomCompany(), RandomPastDate());
return data;
}

public static TheoryData<string, string, DateOnly, string?, string?, DateOnly?> AllOptions()
{
var data = new TheoryData<string, string, DateOnly, string?, string?, DateOnly?>();
for(var i = TestRepetitions - 1; i >= 0; i--)
data.Add(RandomJobTitle(), RandomCompany(), RandomPastDate(), WaffleOrNull(), WaffleOrNull(),
RandomFutureDate().OrNull(Faker));
return data;
}
}
19 changes: 19 additions & 0 deletions TestResumeBuilder/data/JobTestData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Bogus;
using resume_builder.models;

namespace TestResumeBuilder;

internal class JobTestData: TestData
{
protected static Faker<Job> BogusJob { get; set; } = new Faker<Job>()
.RuleFor(job => job.Title, RandomJobTitle)
.RuleFor(job => job.Description, RandomTextOrNull)
.RuleFor(job => job.Experience, RandomTextOrNull)
.RuleFor(job => job.Company, RandomCompany)
.RuleFor(job => job.StartDate, RandomPastDate)
.RuleFor(job => job.EndDate, RandomEndDate);

public static string RandomJobTitle() => Faker.Name.JobTitle();
public static string RandomCompany() => Faker.Company.CompanyName();
public static DateOnly? RandomEndDate() => RandomPastDate().OrNull(Faker);
}
38 changes: 38 additions & 0 deletions TestResumeBuilder/data/TestData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Bogus;
using WaffleGenerator;

namespace TestResumeBuilder;

internal class TestData
{
private protected const int TestRepetitions = 10;


private static Random Random { get; set; } = new();
protected static Faker Faker { get; set; } = new();

static private protected int MaxRandomYearsAfterToday()

Check notice on line 14 in TestResumeBuilder/data/TestData.cs

View workflow job for this annotation

GitHub Actions / qodana

Adjust modifiers declaration order

Inconsistent modifiers declaration order
{
DateOnly.MaxValue.Deconstruct(out var maxYear, out _, out _);
DateOnly.FromDateTime(DateTime.Today).Deconstruct(out var todayYear, out _, out _);
return maxYear - todayYear;
}

static private protected int MaxRandomYearsBeforeToday()

Check notice on line 21 in TestResumeBuilder/data/TestData.cs

View workflow job for this annotation

GitHub Actions / qodana

Adjust modifiers declaration order

Inconsistent modifiers declaration order
{
DateOnly.MinValue.Deconstruct(out var minYear, out _, out _);
DateOnly.FromDateTime(DateTime.Today).Deconstruct(out var todayYear, out _, out _);
return todayYear - minYear;
}

public static TheoryData<object[]> RandomArgs() => [Faker.Random.WordsArray(2)];


public static DateOnly RandomPastDate() => Faker.Date.PastDateOnly(MaxRandomYearsBeforeToday());
public static DateOnly RandomFutureDate() => Faker.Date.FutureDateOnly(MaxRandomYearsAfterToday());
public static DateOnly RandomDate() => Faker.Date.BetweenDateOnly(RandomPastDate(), RandomFutureDate());
public static string? RandomTextOrNull() => Faker.Lorem.Paragraph().OrNull(Faker);

public static string Waffle() => WaffleEngine.Text(Random.Next(TestRepetitions), Faker.Random.Bool());
public static string? WaffleOrNull() => Waffle().OrNull(Faker);
}
Loading

0 comments on commit 83dd806

Please sign in to comment.