redwoodjs / redwood

The App Framework for Startups
https://redwoodjs.com
MIT License
16.93k stars 973 forks source link

[Testing] Get Jest up and running #502

Closed RobertBroersma closed 4 years ago

RobertBroersma commented 4 years ago

As discussed on the forum

Goal

To be able to succesfully run yarn rw test after creating a new app and generating new components.

Steps

We already have a bunch of jest related config files over here: https://github.com/redwoodjs/redwood/tree/master/packages/core/config

thedavidprice commented 4 years ago

Related topic --> adding here so it doesn't get lost.

From #181, how do we want to handle:

if additional config is needed, capability for simple config extension managed from either App root or specific to App sides (e.g. web/, api/, etc.).

RobertBroersma commented 4 years ago

I'm looking into the API side of testing. I think the best would be to have a database or a mocked database somehow, and let tests just run the services and assert on said database (through the prisma client perhaps?)

As I mentioned in this topic I think an in-memory SQLite database would be very easy for this.

However as @olance also mentioned in that topic: databases are different, you can't just swap out a Postgres databse for an in-memory SQLite database.

However if we're thinking of Redwood as the ideal future, we could argue that it's Prisma's job to deal with the database, and we don't care about which database is used, we're only interfacing with the Prisma client.

I see 2 options:

  1. We somehow spin up a postgres instance for the tests. (See this repo for example). This sounds slow to me, but I haven't tried it yet.
  2. In-memory database using SQLite. This is currently not implemented in Prisma, but I suppose we could help out there if this is feasible.

Other things: There's a dedicated package by the Prisma team, which is currently umaintained, but could be promising in the future. It uses the method of spinning up a database. Perhaps we could continue a fork, or contribute to that package? Or wait?

Let me know what you think or if any or none of that makes sense! @thedavidprice @olance @peterp

olance commented 4 years ago

However if we're thinking of Redwood as the ideal future, we could argue that it's Prisma's job to deal with the database, and we don't care about which database is used, we're only interfacing with the Prisma client.

If by this you mean: we leave the DB choice to the user and don't try to interfere because it's Prisma's responsibility, then I agree. If however you mean: we want to use SQLite and we shouldn't have to care because Prisma will adapt to whatever DB is being used, then I don't 😅

And actually, I don't think it's a matter of agreeing or not: there's a range of features that exist on Postgres that do not on SQLite (thinking about enums for instance, but there's probably more). And Prisma will for sure adapt from one to another when features exist on both sides, but it cannot make up for missing features between the two systems.

Coming from Rails, I see a third options: it's the responsibility of the developer to spin up their own DB. I think trying to be smarter than this would come at a price on flexibility, putting unnecessary constraints on the developer's setup.

The way Rails does this, is by having a configuration file for DB credentials, such as:

development:
  adapter: mysql
  encoding: utf8
  reconnect: false
  database: db_dev
  pool: 5
  username: root
  password:
  socket: /tmp/mysql.sock

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  adapter: mysql
  encoding: utf8
  reconnect: false
  database: db_test
  pool: 5
  username: root
  password:
  socket: /tmp/mysql.sock

I fill in the information depending on my own setup, and things are ready to roll! I really don't think it's asking too much to require the devs to have their own db running when they want to use something else than SQLite.

RobertBroersma commented 4 years ago

Thanks for the explanation. I'm not so hot on databases and their features, which is why I like to use tools like Prisma. 😄

I've never used rails, but I the idea of just configuring another DB for tests LGTM. This is kind of what I've been doing in my experiments using Cypress with Prisma; just exporting a different DATABASE_URL for Prisma to consume. I think it could be (almost) as simple as that?


And actually, I don't think it's a matter of agreeing or not: there's a range of features that exist on Postgres that do not on SQLite (thinking about enums for instance, but there's probably more). And Prisma will for sure adapt from one to another when features exist on both sides, but it cannot make up for missing features between the two systems.

On a sidenote I remember I was using enums in SQLite with Prisma not too long ago. Of course that's "fake" on the SQLite side, but the Type checking by Prisma Client is real.

They recently removed that, but might bring it back in the shape of Polyfills: https://github.com/prisma/specs/issues/382

Like I said I'm not much of a backend developer, so I kind of get the problem, but I'm having some trouble coming up with a concrete example where a SQLite DB in a test wouldn't work/would make the test bad when I'm using Postgres in the actual application. Do you have an example for that?

olance commented 4 years ago

Hmmm... I guess if I'm building an app with geolocation features, I would choose to use Postgres with its postgis extension to handle that. Then I guess I wouldn't be able to have tests running for those queries that need postgis, if I can't provide my own database instance to the tests process. Also if I'm using stored procedures or certain built-in functions from postgres/MySQL, those wouldn't be available in another DB system than the one I chose.

I don't have such an extended experience myself that I'm gonna be able to find the example that solves the conversation I believe... however I do think we can look at it this way:

On that last point, here are a few ideas:

RobertBroersma commented 4 years ago

I don't have such an extended experience myself that I'm gonna be able to find the example that solves the conversation I believe... however I do think we can look at it this way:

  • in the end, it's a matter of convention over configuration: finding sane defaults that make the DevX seamless for 90% of the devs, while allowing overrides for the other 10% that want to do differently
  • if The Redwood Way™️ remains that SQLite is used in dev by default, then I think we should use SQLite in tests by default
  • however I think there should be an easy way to override this choice for those like me who prefer having a dev environment closer to their prod environment

I think this is good. Kind of what I have in my head! Default simple SQLite (possibly in-memory if that gets support) and override with own DB when needed.

On that last point, here are a few ideas:

  • Could Prisma's datasources be used to mimic the YAML filed I copied earlier? If so, then Redwood could generate a default schema.prisma file that includes a prod, dev and test datasource. The provider and url fields can then be set independently for each. That would work only if there's a way to tell Prisma which datasource it should be using when running commands such as migrate, and I don't know if that's how it's meant to be used.

Not exactly (I think), but you could get the same effect using environment variables in your schema.prisma. Perhaps we could discuss with the Prisma team (they probably have some ideas on testing as well?), but for now I think a nice solution could be to mimic the YAML you posted in redwood.toml. Since Redwood abstracts the calls to the prisma cli, it could use the values from redwood.toml as env variables in schema.prisma.

olance commented 4 years ago

think a nice solution could be to mimic the YAML you posted in redwood.toml.

👍

peterp commented 4 years ago

@RobertBroersma I think what you've suggested so far is super reasonable, especially based off of this comment: https://github.com/prisma/prisma-client-js/issues/317#issuecomment-574164787