Skip to content

rayshader/cp2077-red-test

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Red Test

Cyberpunk 2077 GitHub License Donate

Tiny Redscript framework to run unit tests with helper functions.

Getting started

  1. Install requirements:
  • Codeware v1.8.0+ (in scripts/Codeware for autocompletion)
  1. Clone repository in your scripts directory:
git submodule add https://github.com/rayshader/cp2077-red-test.git scripts/RedTest/
  1. Create a Test directory:
mkdir -p scripts/Test/
  1. Add a test:

File: scripts/Test/MathTest.reds

  • Rename MathTest to your convenience.
  • Change <ModName> with the name of your mod.
public static func Add(a: Int32, b: Int32) -> Int32 {
  return a + b;
}

public class MathTest extends BaseTest {

  public func Create() {
    this.m_modName = "<ModName>";
    this.m_name = "Math";
  }

  public func Setup() {
    // e.g. get references before running tests.
  }

  private cb func Test_Add() {
    let actual = Add(5, 5);
    let expect = 10;

    this.ExpectInt32("5 + 5 == 10", actual, expect);
  }

  /*
                  | Start with prefix "Test_" to
                  | automatically discover your test.
                  v
  private cb func Test_() {
          ^
          | Callback is required!
  }
  */
}
  1. Create entry-point and register your test:

File: scripts/Test/Main.reds

public class MainTest extends ScriptableSystem {
  private let m_runner: ref<RedTest>;

  /// Lifecycle ///

  private func OnAttach() {
    this.m_runner = new RedTest();
    this.m_runner.Setup("MathTest", [
      new MathTest()
    ]);
  }

  private func OnDetach() {
    this.m_runner.TearDown();
  }
}
  1. Install scripts in game directory.
  2. Run the game.
  3. Open CET and show Game Log popup.
  4. You should see tests result.

DON'T include tests in the release of your mod!

Functions

ExpectBool(name: String, actual: Bool, expect: Bool) -> Bool

ExpectInt8(name: String, actual: Int8, expect: Int8)
ExpectInt16(name: String, actual: Int16, expect: Int16)
ExpectInt32(name: String, actual: Int32, expect: Int32)
ExpectInt64(name: String, actual: Int64, expect: Int64)

ExpectUint8(name: String, actual: Uint8, expect: Uint8)
ExpectUint16(name: String, actual: Uint16, expect: Uint16)
ExpectUint32(name: String, actual: Uint32, expect: Uint32)
ExpectUint64(name: String, actual: Uint64, expect: Uint64)

ExpectFloat(name: String, actual: Float, expect: Float)
ExpectDouble(name: String, actual: Double, expect: Double)

ExpectString(name: String, actual: String, expect: String) -> Bool
ExpectUnicodeString(name: String, actual: String, expect: String) -> Bool

ExpectCName(name: String, actual: CName, expect: CName) -> Bool
ExpectResRef(name: String, actual: ResRef, expect: ResRef) -> Bool
ExpectTweakDBID(name: String, actual: TweakDBID, expect: TweakDBID) -> Bool

You can use ExpectString to test for enums like this:

enum Animal {
  Dog = 0,
  Bird = 1
}

let actual = Animal.Bird;

ExpectString("Is a bird", s"\(actual)", "Bird");

Asynchronous

You can write asynchronous tests (e.g when using callbacks). You need to tell the framework test class is asynchronous:

import Codeware.*

// Custom callback, implementation is not defined for brevity.
public class CustomCallback {
  // ...
  public static func Create(target: ref<IScriptable>, fn: CName, opt args: array<Variant>) -> ref<CustomCallback> {
    // ...
  }

  public func Call() {
    // ...
  }
}

// Suppose this function will run in background and execute our callback
// when its job is finished.
public static func CallAsyncFunction(callback: ref<CustomCallback>) -> Void;

public class SpawnTest extends BaseTest {

  public func Create() {
    // ...
    this.m_isAsync = true; // REQUIRED
  }

  /*
                             | callback to execute when test is finished.
                             v
  */
  private cb func Test_Spawn(done: ref<CallbackTest>) {
    let callback = CustomCallback.Create(this, n"Async_Spawn", [done]);

    // Start a fake background job.
    CallAsyncFunction(callback);
  }

  // Called when background job is finished.
  private cb func Async_Spawn(done: ref<CallbackTest>) {
    this.ExpectBool("Assert", true, true);

    // Tell framework this unit test is finished.
    done.Call();
  }

  // Synchronous test can also be declared in an asynchronous context.
  private cb func Test_Sync(done: ref<CallbackTest>) {
    // Do synchronous stuff here.
    this.ExpectBool("Assert", true, true);

    // You still need to tell the framework this unit test is finished.
    done.Call();
  }
}

About

Tiny Redscript framework to run unit tests.

Resources

License

Stars

0 stars

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages