fledware / GodotXUnit

MIT License
31 stars 5 forks source link

hack-example Branch is working => so far #8

Open GeorgeS2019 opened 3 years ago

GeorgeS2019 commented 3 years ago

https://github.com/fledware/GodotXUnit/tree/hack-example Godot Version: 3.3.rc7.mono Windows 10:

Step 1

GodotProjectName.csproj

<Project Sdk="Godot.NET.Sdk/3.3.0">
  <PropertyGroup>
    <TargetFramework>net472</TargetFramework>
    <LangVersion>8.0</LangVersion>
    <RootNamespace>GodotProjectName</RootNamespace>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
    <PackageReference Include="xunit" Version="2.4.1" />
    <PackageReference Include="xunit.runner.utility" Version="2.4.1" />
  </ItemGroup>
</Project>

Step 2

GodotProjectName.dll

    [XunitTestCaseDiscoverer("GodotXUnitApi.Internal.GodotFactDiscoverer", "GodotProjectName")]
    // ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
    public class GodotFactAttribute : FactAttribute
    {
    }

Known issues

rexfleischer commented 3 years ago

Thanks for testing this! This is definitely the way to go for the new build system if people are ok with having the test assets in with the same assembly. I agree with the benefits here. Maybe there should be a second release that is for single project builds?

Visual Studio 2019 debug tests no longer work

Did they ever work? I've never been able to get it to work.

GeorgeS2019 commented 3 years ago

@rexfleischer I can get the Xunit [Fact] tests of GodotXUnit of the master branch to work in VS2019. But now, no more. Not sure why.

GeorgeS2019 commented 3 years ago

@rexfleischer Still, we need to figure out the productive way TO DO WHAT SHOULD Be ROUTIME, unit and integration testing in Godot for c#.

knightofiam commented 3 years ago

I've got this setup working for the hack-example branch in JetBrains Rider 2021.2.1, Godot 3.3.3.stable.mono, & macOS Big Sur 11.6.

@GeorgeS2019 Thank you! Failed to get it working for several hours before I found your solution.

derkork commented 3 years ago

I have this setup working within Rider 2021.2, Godot 3.3.3 and Windows. After I have patched the Rider test runner to work with GodotXUnit I can even run tests directly from Rider. I wasn't able to get the main branch working but the hack-example branch is a lot easier to set up and works. I can now run tests from the IDE and the Godot editor and thanks to GodotXUnit having a CLI runner I also have a CI solution. I think this is really the way to go. I'm not quite sure why you would need to have this multi-project setup, @rexfleischer could you maybe elaborate on that?

derkork commented 3 years ago

In case you also want to patch the Rider test runner, these are the lines to change:

namespace RiderTestRunner
{
    // ReSharper disable once UnusedType.Global
    public class Runner : GodotTestRunner // <--- here
    {
        public override void _Ready()
        {
            GDU.Instance = this;  // <--- and here
            var textNode = GetNode<RichTextLabel>("RichTextLabel");
            foreach (var arg in OS.GetCmdlineArgs())
rexfleischer commented 3 years ago

@derkork There are a couple reasons this has to be in multiple projects (although, I wouldn't mind being proven wrong if I am!):

If these are incorrect, please let me know. Also, I really like the RiderTestRunner you did. Where can I find docs on this? The few quick searches I did just sent me to unity.

derkork commented 3 years ago

The Rider test runner is actually written by @van800 who also maintains the Godot plugin for Rider. I have just patched it up so that it skips the GodotXUnit runner but still initialized the GDU object. The original can be found at https://github.com/van800/godot-demo-projects/tree/nunit/mono/dodge_the_creeps/RiderTestRunner . You need to put this into your project, but the Godot plugin for Rider will actually tell you this when you try to execute tests without having it.

As for the patching of the assembly name, thats a sort of unfortunate design of xUnit to not allow to add a discoverer programmatically. I wonder if this would work:

This way GodotFact and the discoverer are always in the same assembly and and you don't have to manually patch the assembly name. Drawback - the project will probably not compile until you pull those dependencies from Nuget.

Alternatively, the plugin could probably do a quick search/replace over GodotFact.cs and patch in the current assembly name on plugin start if it is wrong. That is probably only a few lines of code.

Then the only thing remaining is the additional classes that you pull in that you don't need for runtime, but I'm not sure if this is really that big of a deal. One could also maybe wrap the CS-classes in some #if !RELEASE or something like this, so for a release build you could set a RELEASE preprocessor flag and the classes would disappear.

van800 commented 3 years ago

I have once written an explanation on how Rider runs tests inside godot game, please see https://github.com/JetBrains/godot-support/pull/58

rexfleischer commented 3 years ago

@derkork I was able to get master working again with multiple projects. I still really like the idea of of putting the GodotFact and whatnot into a separate dll. I tested it on my game and it worked just fine, but only in the godot editor. Good stuff with the #if !RELEASE stuff, I didn't know about that and that seems to be the way to go.

@van800 Thanks, that link is very helpful. I moved both those files into the directory, and I was able to get tests running and passing. The only problem I've found is when the test tries to change the scene. It seems like when the scene gets changed, it will just never recover and the runner script goes away. If I have time, I'll be happy to look into this.

Also, would it make sense to search for the scene with addons/**/RiderTestRunner/Runner.tscn, and whatever is found first is the runner? That way any addon can setup their own way to hook into the RiderTestRunner without having to add addon code outside of the addon directory. If I get back to godot full time again, I was probably going to make a similar test integration for kotlin, because that is by far my preferred language. But following that pattern, it would be awesome to have a godot addon that can hook into multiple test runners by this type of convention.

rexfleischer commented 3 years ago

Following a lot of what @GeorgeS2019 did, this brought me to this PR: https://github.com/fledware/GodotXUnit/pull/10

I merged it and will have a release on the addon site tonight.

rexfleischer commented 3 years ago

What I've got so far for the RiderTestRunner is at: https://github.com/fledware/GodotXUnit/tree/rider-test-runner

van800 commented 3 years ago

That's cool, thank you!

  1. Except the mentioned trick to use #if RELEASE, there is also another one to use conditions in the csproj like:

    <Compile Include="RiderTestRunner\Runner.cs" Condition="'$(Configuration)' == 'Debug' " />

    As a plus, when you switch SolutionConfiguration in the IDE it would show you actual files included image

  2. Yes, Godot Support plugin can search for RiderTestRunner/Runner.tscn in the multiple locations. But I would rather throw error in case multiple runner are found. Would it be fine with you?

rexfleischer commented 3 years ago

Both of those are awesome! That makes me worry much less about bloating code with editor/test stuffs.

As for throwing the error, I think that's the best way to go. I'm just thinking of the case where people might pull down another addon for trying out or for utils. Or, maybe they don't like how GodotXUnit does it but they don't want to modify GodotXUnit because its external code (I strongly prefer not to change others internal code), or they want to extend another persons runner to fix an issue specific to them. But, with those scenarios, I think I'm wanting to future proof too much. Throwing the error makes a lot of sense and would be simpler and easier to use. Only when needed making it more complicated to handle multiple.

With that said, I completely agree with throwing the error.

van800 commented 3 years ago

I have made the changes, allowing moving RiderTestRunner/Runner.tscn anywhere inside the solution. https://github.com/JetBrains/godot-support/commit/0e3145ede2c28c0c2d9e0ddc2eddb06b9a6ad2f0 https://github.com/van800/godot-demo-projects/commit/f903d8ca5e542eb225a51b40a3a415262d0e716a

rexfleischer commented 3 years ago

That's fantastic. Thanks for the fast turn around!

van800 commented 3 years ago

Ok! Plugin 2021.3.79, which is compatible with Rider 2021.3 EAP builds has this change now.

I want to refence GodotXUnitApi as nuget from my example project, but yet it is not packed, so I tried to pack it. See https://github.com/fledware/GodotXUnit/pull/13 Unfortunately not yet fully completed (it compiles and works as before, but doesn't get automatically packed). I am missing something, but don't what exactly. I plan to return to it, but if anyone has idea how to finish it then please take over.

GeorgeS2019 commented 2 years ago

@rexfleischer I revisit using this branch.

Together with the new commits in the main branch.

It seems stable with many wishes I need. I summarize Good-To-Have here => how to combine new tested ideas from different Unit test c# frameworks into one framework.

I routinely use one SLN generated by Godot to coordinate test driven libraries outside Godot before bring them to Godot for final testing involving Godot classes.

Still refining how best to do that well.

Still it would be nice to be able to do breakpoints, watch etc. within visual studio 2019/2022

rexfleischer commented 2 years ago

Ok, I think I'm going to merge what @van800 did into main because it seems to be mostly just broken for me. my dev machine did just die on me about 3 weeks ago :'( ... although, I will have to figure out the issue in CI, but it seems like you might be onto something.