CounterStrikeSharp icon indicating copy to clipboard operation
CounterStrikeSharp copied to clipboard

Proposal: Make Plugins Testable

Open yonilerner opened this issue 1 year ago • 3 comments

Hey friends, I have a sorta insane idea I want to run by you. Ive been working on my plugin with CounterStrikeSharp and its great, but I do most of my development on macos, so Ive been organizing my code so that much of it can run outside of the game server environment so i can test it on my mac.

My goal was to make my plugin testable without having to run a server. Both because of my personal environment limitations, but also because I think having plugins be testable in general will make them more reliable and improve the quality of plugins.

So I started playing with the idea of having everything that interacts with a server be wrapped in interfaces that would allow my plugin code to be 95% runnable outside the server, with a default implementation of each interface of course requiring the server. And then separately you could have test implementations to run your logic in a testable environment without the server present.

This PR has a proof of concept of the interfaces and a concrete implementation, but no test implementation yet https://github.com/yonilerner/cs2-retakes-allocator/pull/73. Because I cant force CSS classes to implement my interfaces, I have to rewrap everything. Basically having every class (or at least the big ones like CCSPlayerController to start) implement an interface (eg. ICCSPlayerController) that defines all the methods and fields but would then allow tests to mock any of them (saves all the wrapping hassle).

Here are some key lines of code from my example PR that demonstrates the idea:

  • "global" interface: https://github.com/yonilerner/cs2-retakes-allocator/pull/73/files#diff-1cfa7fb21119ea24215e2b6df73060d0d8bd4f4ea6bd3e8e015cc1c23cfc4f4e
  • concrete implementation that actaully does things: https://github.com/yonilerner/cs2-retakes-allocator/pull/73/files#diff-93a89dac843b335c58ccddd7a4480124c9f2a7da93931c73616be1142b64b553
  • Testable function that uses the interface to do logic: https://github.com/yonilerner/cs2-retakes-allocator/pull/73/files#diff-32316111aba20e9746d411d736fea60f57574c05a5f53b43134f0b35d81dfadbR14
  • How that function gets called: https://github.com/yonilerner/cs2-retakes-allocator/pull/73/files#diff-9a978eb8236c5e3558e27805427517a303f95b12092f4d72a21ec7e69a57208dR412-R413

This is of course not the only way to make plugins testable, just the one I started playing around with. Before I went further on this work, I wanted to pose to the community: Is there general interest in making plugins (and even CounterStrikeSharp itself) more testable? Is this something that people would find value including in CounterStrikeSharp by default, so that any plugin - and CounterStrikeSharp internals - can be easily tested without having to jump through the hoops I did?

Let me know what you think. Thanks!

yonilerner avatar Jan 21 '24 03:01 yonilerner

An interface for the CCSPlayerController would help me write unit tests for the Menus as I'm struggling to mock that class without it. 👍

B3none avatar Jan 22 '24 22:01 B3none

I have a draft PR #331 which auto-generates interfaces for schema classes; though how we can update the core to use these interfaces without breaking backwards compat is up in the air at this point.

roflmuffin avatar Feb 22 '24 01:02 roflmuffin

Oh this is incredible, Im gonna poke around next time I have a chance. Thank you!

yonilerner avatar Feb 22 '24 04:02 yonilerner