Skip to content

Pythagora-io/pythagora

main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
bin
 
 
src
 
 
 
 
 
 
 
 
 
 
 
 

Text changing depending on mode. Light: 'So light!' Dark: 'So dark!'

Generate 90% code coverage with integration tests in 1 hour


Pythagora is a tool that generates integration tests for your Node.js app by recording server activity without you having to write a single line of code.

🏁 Alpha version

This is an alpha version of Pythagora. To get an update about the beta release or to give a suggestion on tech (framework / database) you want Pythagora to support you can 👉 add your email / comment here 👈 .

🏗️ How it works

To integrate Pythagora into your Node.js app, you just need to install the pythagora package

npm install pythagora

and run the Pythagora capture command. Then, just play around with your app and from all API requests and database queries Pythagora will generate integration tests.

1. Capturing requests

Pythagora records all requests to endpoints of your app with the response and everything that's happening during the request. Currently, that means all Mongo and Redis queries with responses (in the future 3rd party API requests, disk IO operations, etc.). Then, when you run the tests, Pythagora can simulate the server conditions from the time when the request was captured.

2. Running tests

When running tests, it doesn’t matter what database is your Node.js connected to or what is the state of that database. Actually, that database is never touched or used —> instead, Pythagora creates a special, ephemeral `pythagoraDb` database, which it uses to restore the data before each test is executed, which was present at the time when the test was recorded. Because of this, tests can be run on any machine or environment.

If a test does an update to the database, Pythagora also checks the database to see if it was updated correctly.

Pythagora Alpha Demo

Watch Pythagora Demo (3 min)



⚙️ Setup

  1. Install Pythagora by running

    npm install pythagora
    
    And that's it! You are ready to start recording your integration tests!

🎥 Capturing tests

  1. From the root directory run Pythagora in a capture mode first to capture test data and mocks.

    npx pythagora --init-command "my start command" --mode capture
    
    Eg. if you start your Node.js app with nest start then the command would be:

    npx pythagora --init-command "nest start" --mode capture
    
  2. Click around your application or make requests to your API. Pythagora will capture all requests and responses.

    NOTE: To stop the capture, you can exit the process like you usually do (Eg. Ctrl + C)

▶️ Executing tests

After you captured all requests you want, you just need to change the mode parameter to --mode test in the Pythagora command.

npx pythagora --init-command "my start command" --mode test



📖 Options

These are available options for Pythagora command:


--rerun-all-failed (runs again only tests that failed in previous run)

npx pythagora --init-command "my start command" --mode test --rerun-all-failed

--delete-all-failed (deletes all previously failed tests)

npx pythagora --init-command "my start command" --delete-all-failed

--delete testId (deletes test with testId)

npx pythagora --init-command "my start command" --delete testId

--pick endpoint1 endpoint2 (starts capturing only listed endpoints)

npx pythagora --init-command "my start command" --mode capture --pick /endpoint1 /endpoint2

--ignore endpoint1 endpoint2 (starts capturing but ignores all listed endpoints)

npx pythagora --init-command "my start command" --mode capture --ignore /endpoint1 /endpoint2

--review (runs review process of failed tests, allowing you to update old captured tests or to delete them)

npx pythagora --review



📝 Code Coverage Report

Code coverage is a great metric while building automated tests as it shows us which lines of code are covered by the tests. Pythagora uses nyc to generate a report about code that was covered with Pythagora tests. By default, Pythagora will show you the basic code coverage report summary when you run tests.

If you want to generate a more detailed report, you can do so by running Pythagora with --full-code-coverage-report flag. Eg.

npx pythagora --init-command "my start command" --mode test --full-code-coverage-report

You can find the code coverage report inside pythagora_tests folder in the root of your repository. You can open the HTML view of the report by opening pythagora_tests/code_coverage_report/lcov-report/index.html.


In case you don't want the code coverage to be shown at all while running tests, you can run the tests with --no-code-coverage parameter. This is helpful during debugging process since the code coverage report can clash with your IDE's debugger.



Authentication

For authentication we support JWT, sessions stored in Redis and sessions stored in MongoDB. First 2 cases cases (JWT and sessions stored in Redis) should work just fine without any additional implementation but for session that are stored in MongoDB you need to add this one line of code:
if (global.Pythagora) global.Pythagora.authenticationMiddleware = true;

just before your authentication middleware. For example, if you are using express-session you would have to add our line of code just above your middleware that is managing sessions in your DB, like this:

...

if (global.Pythagora) global.Pythagora.authenticationMiddleware = true;

app.use(session({
    secret: 'my-secret',
    resave: false,
    saveUninitialized: false,
    cookie: {
        maxAge: 60 * 60 * 1000
    },
    store: MongoStore.create({
        mongoUrl: mongourl,
        mongoOptions: {
            useNewUrlParser: true,
            useUnifiedTopology: true
        }
    })
}));

...

That's it! You are ready to go and all your API requests with authentication should PASS!



🗺️️ Where can I see the tests?

Each captured test is saved in pythagora_tests directory at the root of your repository. Each JSON file in this repository represents one endpoint that was captured and each endpoint can have many captured tests. If you open these files, you will see an array in which each object represents a single test. All data that's needed to run a test is stored in this object. Here is an example of a test object.
{
  "id": "b47cbee2-4a47-4b2c-80a0-feddae3081b3",
  "endpoint": "/api/boards/", // endpoint that was called
  "body": {}, // body payload that was sent with the request
  "query": {}, // query params that were sent with the request
  "params": {}, // params that were sent with the request
  "method": "GET", // HTTP method that was used
  "headers": { // headers that were sent with the request
    "x-forwarded-host": "localhost:3000",
    ...
  },
  "statusCode": 200, // status code that was returned
  "responseData": "...", // response data that was received
  "intermediateData": [ // server activity that was captured during the request
    {
      "type": "mongo", // type of the activity - mongo query in this case
      "req": { // data for mongo query that was executed
        "collection": "users",
        "op": "update",
        "options": {},
        "_conditions": {
          "_id": "ObjectId(\"63f5e8272c78361761e9fcf1\")"
        },
         "_update": { // data that needs to be updated
            "name": "Steve",
            ...
         }
      },
      "preQueryRes": [ // data that was present in the database before the query was executed
        {
          "_id": "ObjectId(\"63f5e8272c78361761e9fcf1\")",
          "name": "Michael",
          ...
        }
      ],
      "mongoRes": [ // data that was returned by the query
        {
          "_id": "ObjectId(\"63f5e8272c78361761e9fcf1\")",
          "name": "Steve",
          ...
        }
      ],
      "postQueryRes": [ // data that was present in the database after the query was executed
        {
          "_id": "ObjectId(\"63f5e8272c78361761e9fcf1\")",
          "name": "Steve",
           ...
        }
      ]
    }
  ],
  "createdAt": "2023-02-22T14:57:52.362Z" // date when the test was captured
}



⛑️ Support

For now, we support projects that use:

Other technologies that Pythagora works with:

Apollo server GraphQL NestJS Next.js Nuxt.js PostgreSQL
Logo 1 Logo 2 Logo 3 Logo 1 Logo 1 Logo 1
Upcoming Upcoming Upcoming

🔗 Connect with us

💬 Join the discussion on our Discord server.

Star this repo to show support.