Debugging and Errors

This section does not contain any design requirements (i.e. you could complete the whole project without reading this section). However, we’ve compiled our general guidelines for design, development, and testing.

Debugging in VSCode

Once the extensions are installed we can now follow the debugging flow:

  • Set breakpoints. To set a breakpoint in your code, Navigate to the line where you want your breakpoint to be, and click on the left side of the line number. You should see a red dot appearing next to the line number, which indicates that a breakpoint has been set.

    Setting a breakpoint.

  • Run a test. To debug a test case and peek around the breakpoint, navigate to the client_test/client_test.go file, and click on the debug test button above the test case that you want to run. Immediately after, the debugger will start. If your debugger doesn’t pause at breakpoints you’ve set, this means that your code flow never went through any lines of code that you’ve set a breakpoint on.

    Debug test.

  • Navigate the debugger. The golang debugger has a really convenient and powerful interface. There are a couple sections you should especially be aware of:
    • You can step through your code using the menu bar at the center top of the screen just above the code editor (outlined in blue in the image below). Hover your mouse over each function to see the keyboard shortcut for each of these. This is a very important feature, so get familiar with each and every button.
    • You can use the local variables at the top left quadrant of your screen (dash outlined in red in the image below), which displays the variable name and their values. For nested structures, you can click the expand button to view variables inside the struct.
    • You can use the watch section at the middle left quandrant of your screen (circled in green in the image below) to constantly evaluate golang expressions. Some of the thing you can use it for is to constant check the length of an array, which you can do with call len([variable]). To constantly evaluate functions, you need to append the function call with call for watchpoints.
    • You can check the call stack in the call stack section, and edit breakpoints in the breakpoints section.

      Using the debugger.

Debugging a Single Test Case

To learn how to debug a single test case, refer to our section on how to run a single test case.

Errors While Debugging

Here are solutions for a couple errors that you may run into while running the debugger.

  • Couldn't find dlv at the Go tools path pops up when you click the Debug test button, but running go test -v works fine. This seems to be a problem due to recent updates to the Go extension on VSCode (and its compatability with delve). There are a couple possible solutions:
    • To solve the problem solely in VSCode, run Go: Install/Update Tools from the Command Palette. You can access the Command Palette by running Cmd + Shift + P in Mac or Ctrl + Shift + P in Linux/Windows. Then mark dlv and dlv-dap from the menu, and hit okay. This should start the update. You may need to restart VSCode after doing this.
    • For macOS users, you can also just run brew install delve.
  • A general solution for other problems is making sure that you’re running Go v1.20. This is the suggested version of Go (you can check your version of Go by running go version in your terminal).

Common Gradescope Errors

  • Tests failed to compile! Grading cannot continue. but everything works when you run go test locally: This means that tests in your client_test.go file utilize struct attributes or helper functions (not the core API functionality). However, since these tests are run against the staff implementation, you cannot use struct attributes in your client_test.go (otherwise, you’d be assuming what structs in the staff implementation look like).
    • Fix: If you want tests that check against struct attributes or helper function functionality, put these in the unit test file! he separation between unit and client tests is that unit tests test for your implementation correctness and can be implementation-specific (so you can access any extra client helper functions or struct attributes) while client/integration tests are implementation-blind, just checking that the overall functionality is correct.
    • The distinction between the client_test.go integration tests and any tests you write in client_unittest.go as unit tests is that integration tests should pass on anyone’s implementation whereas unit tests may be specific to your design. For integration tests, we want you to write tests to ensure the correct functionality of the client API that would hold under your implementation, the staff implementation, Evanbot’s implementation, etc. These are functionality and security tests (so you can write tampering tests too!), and shouldn’t be dependent on what structs the staff solution has.

Warning: Please remove all FSpecify statements when you submit to the autograder (otherwise, the autograder will only run tests labelled FSpecify) or potentially break the autograder. We cannot promise we will re-run the autograder for you if you forgot to remove them.