1.0.0 • Published 2 years ago

qa-automation-order-router v1.0.0

Weekly downloads
-
License
ISC
Repository
github
Last release
2 years ago

qa-automation-order-router

npx mochawesome-merge ./mochawesome-report/CITADEL/.json ./mochawesome-report/CITADEL/.json -o ./mochawesome-report/CITADEL/output.json

Directory Structure

lib/ - contains reusable code for tests

  • order/ - all code needed to build and run an order test case
    • strategy-builders/ - contains utility methods for building an order strategy (vertical, iron condor, etc)
    • test-cases/ - builds listst of TestCases to be used in tests. A TestCase instance has all the data needed to build an order
    • order-builder.js - Makes building an order at runtime very easy. All of its methods return this, so you can chain calls to it. For example: new OrderBuilder().market().day().build(). This file also includes OrderLegBuilder and OptionLegBuilder for building order legs.
  • service/ - Each file in here is responsible for making remote http requests to our microservices. They all utilize TwHttpClient to make the requests.
    • instrument.js - fetches instruments (futures, equities), option chains, future products, etc. Any requests to instruments-api should be in here.
    • order.js - makes http requests to order-api.
    • quotes.js - makes http requests to market-data-server.
  • test/ - contains reusable code useful for running tests
    • account-context.js - represents a single account with a live session. Allows you to make http requsts using the service/ classes. If you need to make http requests with multiple accounts, instantiate multiple AccountContext with different credentials.
    • global-setup.js - this is a mocha "root hook plugin". It gets run before entire test suite. In parallel mode, this will be run before each test suite process (each test file is a test suite). Make sure you --require it when you run your tests. See here for more info.
    • instrument-context.js - responsible for storing/caching all instrument data needed during test runs.
    • shared-contexts.js - loads all data needed for a test run. For example, loginEquitiesAccount can be called in a before() block to load equities, option chains, and underlying quotes to be used in test cases. All the data will be stored in instrumentContext, which tests have access to thanks to global-setup.js.
    • shared-tests.js - any repetitive code used in test runs can be put here.
  • util/ - utility classes and methods
    • credentials.js - holds a username, password, and account number that is used by AccountContext to login.
    • enums.js - a bunch of enum objects
    • option-expiration.js - utility methods for getting data from an option expiration
    • quote.js - utility methods for getting data from a quote
    • response.js - utility methods and classes for handling http responses. Contains a ResponseContainer class which holds the response body, any response errors, and the raw axios response object.
    • tw-session.js - holds an auth token and a remember token which get populated when accountContext.login() is called. TwHttpClient holds a reference to a TwSession so it can make requests to our back-end using the session.token.
  • tw-http-client.js - makes axios http requests. Each service in services/ has a reference to a TwHttpClient instance that it uses to make http requests. TwHttpClient automatically adds the Authorization header to each request using its TwSession instance.

Using the lib/ code

Here is an example of how you might find the lib/ code helpful:

Building a list of Vertical spread orders and submitting them

  1. Create an instance of AccountContext and login()
before() {
  const credentials = new Credentials('myusername', 'mypassword', '5WT11111')
  // this.instrumentContext is available to all tests. It is set in the `global-setup.js` root hook plugin
  const accountContext = AccountContext.create(credentials)
  // POST /sessions to get an auth token. Store the auth token in accountContext.session
  await accountContext.login()
}

For convenience, we have a loginDefaultAccount, loginEquitiesAccount, and loginFuturesAccount in shared-contexts.js that does all this for you.

  1. Load equities, option chains, and underlying quote
const symbols = ["AAPL"]
const instrumentContext = InstrumentContext.create(accountContext.userSession)
await instrumentContext.loadEquitiesData(symbols)
await instrumentContext.loadQuotes(symbols)

For convenience, we have a loginAndFetchEquitiesData() method in shared-context.js that does all this for you (including login).

  1. Build some test cases for different orders you'd like to test
// Use the expiration date that is > 1 day from now
const DefaultExpirationOffsetDays = 1
// Spreads should be 10 strikes wide
const DefaultSpreadWidth = 10
// First order leg should be 1 strike OTM
const DefaultAtmOffset = 1
const testCases = [
    new VerticalTestCase("AAPL", DefaultSpreadWidth, DefaultAtmOffset, DefaultExpirationOffsetDays, OptionType.Call, OrderQuantity.QtyOne, Direction.Long, OpenClose.Open, TimeInForce.Day, OrderType.Limit, OrderPrice.Fill, PriceEffect.Debit, OrderStatus.Routed),
    new VerticalTestCase("AAPL", DefaultSpreadWidth, DefaultAtmOffset, DefaultExpirationOffsetDays, OptionType.Put, OrderQuantity.QtyOne, Direction.Long, OpenClose.Open, TimeInForce.Day, OrderType.Limit, OrderPrice.Fill, PriceEffect.Debit, OrderStatus.Routed),
]

For convenience, we have a VerticalFilledTestCases array in lib/order/test-cases/vertical.js that iterates over a bunch of different values (Put/Call, Day/GTC/GTD, Long/Short, Open/Close) and builds test cases.

  1. Build json needed to submit the order, submit the order, and verify its state
testCases.forEach((testCase) => {
    it(`${testCase.description()} order`, async function () {
        // testCase creates an `OrderBuilder`. `OrderBuilder.build()` returns valid json object
        const orderJson = testCase.buildOrder(this.instrumentContext).build()
        let responseContainer
        try {
            // POST /accounts/{accountNumber}/orders/dry-run to see if preflight passes
            responseContainer = await accountContext.orderService.dryRun(orderJson, accountContext.accountNumber)
        } catch (error) {
            // Extract any useful info from the response and log it. Then re-throw the error so the test fails
            console.log(error.message)
            extractNestedErrors(error.response).printHumanReadable()
            console.log("Account number: ", accountContext.accountNumber)
            console.log("Request body: ", orderJson)
            throw error
        }
        expect(responseContainer.errors.isEmpty).to.be(true)
    })
})

For convenience, we have a verifyDryRunFromTestCase method in shared-tests.js that does all this for you.

Smoke Tests

To run the smoke tests: npm run smokeTest

You can find instructions on running the smoke tests in smoke-tests/README.md.