Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration Test framework and an initial test for Document Code #1291

Open
wants to merge 59 commits into
base: main
Choose a base branch
from

Conversation

steveyegge
Copy link
Contributor

@steveyegge steveyegge commented Apr 6, 2024

This PR introduces the new JB integration test framework, based on the built-in JB testing facilities.

Overview

We only have one test so far, DocumentCodeTest, but:

  • It tests end-to-end communication between JetBrains and the Cody Agent over the jsonrpc protocol
  • It is fully asynchronous and can wait arbitrarily long for tests to complete
  • It can be configured to hit a production LLM; currently there is a stub mock LLM interaction
  • It has two separate validations:
    • one protocol roundtrip (getFoldingRanges)
    • one async client-side operation that awaits the appearance of the first codelens

This serves as a good reference example of using the test framework.

Note that one facility of the test framework is that we use the built-in JetBrains pubsub support to signal to subscribers (the tests) that certain async checkpoints have been reached, which the tests can await.

FixupSession and some other classes are instrumented with these notifications, and the tests subscribe to them.

Caveats

  • There is only one test and it's incomplete
  • I have not yet mocked out the LLM interaction for a full Document Code task/session
  • Even after that, there are many tests left to write.

Test plan

This is a test, so it's part of the test plan for previous PRs.

I have tried not to break anything, so I've verified that on this branch, when using the stevey/jetbrains-tests' branch of sourcegraph/cody`:

  • It's all still behind the CODY_JETBRAINS_FEATURES feature flag
  • Cody works
  • Integration test passes in both cli (gradlew intTest) and from within the IDE

@@ -97,10 +97,12 @@ private constructor(
val conn = startAgentProcess()
val client = CodyAgentClient()
client.onSetConfigFeatures = project.service<CurrentConfigFeatures>()
logger.warn("Starting json-rpc Launcher")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't all that logs be on the info level?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a few extra logging statements at key lifecycle stages of starting the Agent, because I found it tremendously helpful in narrowing down where it was failing when the Agent is pooping out. Which is often. I'll review them all, though, to see which ones we should really keep.

@@ -156,12 +159,27 @@ private constructor(
processBuilder.environment()["CODY_LOG_EVENT_MODE"] = "connected-instance-only"
}

if (ConfigUtil.isIntegrationTestModeEnabled()) {
// N.B. Do not set CODY_TESTING=true -- that is for Agent-side tests.
val testToken = System.getenv("CODY_INTEGRATION_TEST_TOKEN")
Copy link
Contributor

@pkukielka pkukielka Apr 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should reuse tokens and polly.js recording infrastructure we already have in the agent.
This way we won't need to confugure/understand/setup two independent testing environments, and all token management could be taken care of on the agent side.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some test conditions are hard to recreate with production backends. VSCode uses both kinds to good effect.

@@ -47,24 +47,19 @@ class CodyAgentService(project: Project) : Disposable {
FixupService.getInstance(project).getSessionForTask(task)?.update(task)
}

agent.client.onEditTaskDidDelete = Consumer { task ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you reverted my change to the callbacks/lifecycle managenet.
Was that intentional?
Initialising it in FixupService won't work in some cases, e.g. after agent restart.
If that was not intentional, please revert those changes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@steveyegge pinging this comment ^

@@ -25,6 +27,71 @@ class FixupService(val project: Project) : Disposable {
// The last text the user typed in without saving it, for continuity.
private var lastPrompt: String = ""

init {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert those changes or let's discuss offline.

Copy link
Contributor

@dominiccooney dominiccooney left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Putting this back in your queue. The diff looks odd to me—there's a bunch of inline edits changes, and @pkukielka mentioned one revert? in here.

If the edits changes are particularly conflicty, we could also land everything except the edits changes + edits test and drop a trivial hello world type test in there so we can get hacking on other integration tests in parallel with the edit test landing. But if it is close then let's not toil over splitting it up.

applySharedConfiguration(sharedIntegrationTestConfig)
}

// Make sure to set CODY_INTEGRATION_TEST_TOKEN when using this task.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    onlyIf {
        System.env['CODY_INTEGRATION_TEST_TOKEN'] != null
    }

or let's conditionally print an error or something.

Ditto below.

@@ -47,24 +47,19 @@ class CodyAgentService(project: Project) : Disposable {
FixupService.getInstance(project).getSessionForTask(task)?.update(task)
}

agent.client.onEditTaskDidDelete = Consumer { task ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@steveyegge pinging this comment ^

@dominiccooney
Copy link
Contributor

This has conflicts with the actions refactoring in ff37c21. Very tempting to split this up so we can write other tests while closing the loop on edit tests.

Copy link
Contributor

@dominiccooney dominiccooney left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be so great to get these going, can't wait to write some.

A few minor comments inline.

This needs rebasing to pick up the changes where 'edit' and 'workspace edit' produce a boolean.

the protocol changes.

```
CODY_INTEGRATION_TEST_TOKEN=sgp_asdfasdfasdfasdfasdfasdfasdf
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a script in sourcegraph/cody, agent/scripts/export-cody-http-recording-tokens.sh . Can we standardize on using those tokens? Everyone has access to them and there are different variants for rate limited tokens, etc. if we need them down the road.

"CODY_JETBRAINS_FEATURES" to "cody.feature.inline-edits=true",
"CODY_RECORDING_MODE" to "replay",
"CODY_RECORDING_DIRECTORY" to "recordings",
"CODY_RECORD_IF_MISSING" to "false") // Polly needs this to record at all.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...weird!

"CODY_RECORD_IF_MISSING" to "false") // Polly needs this to record at all.

// Common configuration for integration tests.
// TODO: This doesn't actually work.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants