vapor/vapor

Unable to test vapor using .xcodeproj project

nishant-dani opened this issue · 8 comments

Describe the bug

I am using vapor inside my xcodeproj project but if I attempt to run any test it hangs with the error;
'Test runner never began executing tests after launching'.

I narrowed this down to the fact that the main is getting called and that is creating problems for the regular text execution. If I open a new vapor project through the package.swift file directly and invoke the tests the main is not called and the tests are able to proceed as expected.

To Reproduce

Import vapor into existing .xcodeproj
Run Product -> Test

This is the main function;

static func main() async throws {
    var env = try Environment.detect()
    try LoggingSystem.bootstrap(from: &env)
    
    guard let stdLibPath = Bundle.main.path(forResource: "python-stdlib", ofType: nil) else { return }
    guard let libDynloadPath = Bundle.main.path(forResource: "python-stdlib/lib-dynload", ofType: nil) else { return }
    setenv("PYTHONHOME", stdLibPath, 1)
    setenv("PYTHONPATH", "\(stdLibPath):\(libDynloadPath)", 1)
    // Temporarily disable Python
    Py_Initialize()
    print ("Py_Initialize complete")
    
    // we now have a Python interpreter ready to be used
    let app = Application(env)
    defer { app.shutdown() }
    
    do {
        try await configure(app)
    } catch {
        app.logger.report(error: error)
        throw error
    }
    try await app.execute()
}

I assumed this might because of app.execute, but if I remove app.execute in the following manner.

        if NSClassFromString("XCTestCase") == nil {
            app = Application(env)
        } else {
            app = Application(.testing)
        }

        // Rest of the code as before 

        if NSClassFromString("XCTestCase") == nil {
           try await app.execute()
        }

The test fails with a revised error;

Early unexpected exit, operation never finished bootstrapping - no restart will be attempted. (Underlying Error: The test runner exited with code 0 before checking in.)

The tests are mostly irrelevant because it never gets to the tests; (no breakpoints or prints are hit) but this is the test

    func testHelloWorld() async throws {
        try TestEntrypoint.testApp!.test(.GET, "hello", afterResponse: { res in
            XCTAssertEqual(res.status, .ok)
            XCTAssertEqual(res.body.string, "Hello, world!")
        })
    }

Is Vapor entire incompatible with xcodeproj or is there a known workaround for this?

Steps to reproduce the behavior:

  1. Add package with configuration '...'
  2. Send request with options '...'
  3. See error

Expected behavior

The expected behavior is that it will attempt to run the tests.

Environment

  • Vapor Framework version:
  • framework: 4.89.3
  • Vapor Toolbox version:
  • OS version:
  • MacOS Ventura 13.6.1

XCode Version 15.1

Additional context

Add any other context about the problem here.

This sounds like your Xcode project is misconfigured to use your project's main executable as the test runner instead of the xctest binary - hence the invocation of your existing main(), which should never happen when running tests (on macOS and other Apple platforms, when testing an executable target the XCTest framework automatically takes over before it gets to your main() and redirects the runtime to XCTest's entry point; for testing of library targets the separate test runner binary is used - on Linux the separate runner is always used). I wouldn't be able to offer much more in the way of insights without seeing your actual Xcode project - if you'd rather not share it here (very much understandable!), please ping me on Discord (https://discord.gg/vapor) and I'll see if I can be of any help there.

I have setup the test host to be the project's main executable, this is the default setting, otherwise I am unable to access the host functions for logic testing. If I leave that setting as blank the linker will detect undefined symbols errors. I have also pinged you on discord. I am linking with both XCTest.framework and the XCTVapor framework. I had tried also with only the XCTVapor framework.