-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
Server folder restructuring & test tooling & test refactoring #9178
Comments
refs #9178 - Introduce the /services/ folder - Move xmlrpc there - Move slack there - In slack: remove a usage of the settings API that should use settingsCache - In slack: Simplify the tests - Various tiny changes to move towards code consistency
refs TryGhost#9178 - Apps is a service, that allows for the App lifecycle - /server/apps = contains internal apps - /server/services/apps = contains code for managing/handling app life cycle, providing the proxy, etc
@kirrg001 loosely related thing that I wanted to have a discussion about, is the structure of tests going forward. I have a couple of points here which are about doing a little bit of upfront work in order to, long term, significantly reduce time & complexity of testing: Question 1: What sort of tests should we be writing?Below is a table I generated from the latest master build. The numbers in the top are how many of that type of test we have, the numbers in the columns are how long mocha reports the tests took, the total is what Travis says:
It is good to see they take less time in newer versions of node, but the fundamental point is this: We have both concepts of integration AND route tests.
Route tests are slower and more involved than integration tests, but both are ridiculously, significantly slower than unit tests. IMO, we should focus on writing unit tests - we have many many of these and they still take under a minute to run. IMO we can have up to 1 minute of unit tests and life is still good. We should then, probably use a single style of deep testing - either integration or route tests. Or we should have both but for very specific things? i.e. API -> Route tests, "database behaviour" (import, export, migrations) -> integration. I am very much up for deleting a large section of tests if we can identify which ones are not really useful. imagine if we only had one of the routes/integration tests - we would cut our test time by a half! 🎉 Question 2: What tools should we be using?I think, if we narrow down the kinds of tests we write, we can expand the tools we have. I did a quick PR here: #8206 where we discussed some things. But a short list for me would be:
In short, we need to get out of our own way in the tests. Make them run faster, make them easier to write. Invest in tools so that we can test the RIGHT things FASTER. Don't bother testing the wrong things! I would like to discuss this a little bit and then maybe start a wiki page that has guidelines that say "this is how we write tests", so that as we move forward we move towards clear goals. It's easier to work that way than to try to change all of the code base & rewrite all of the tests all in one go. |
refs #9178 * Moved app handling code into services/apps - Apps is a service, that allows for the App lifecycle - /server/apps = contains internal apps - /server/services/apps = contains code for managing/handling app life cycle, providing the proxy, etc * Split apps service tests into separate files * Moved internal app tests into test folders - Problem: Not all the tests in apps were unit tests, yet they were treated like they were in Gruntfile.js - Unit tests now live in /test/unit/apps - Route tests now live in /test/functional/routes/apps - Gruntfile.js has been updated to match * Switch api.read usage for settingsCache * Add tests to cover the basic App lifecycle * Simplify some of the init logic
Good summary 👍
The routing tests are that slow, because each test file (and sometimes even each test case) resets the database and starts/stops the ghost server. That eats lot's of time. This should be improved by changing the way we ensure that the test case can rely on a running ghost server. For example: By default we start the server once, as soon as a test has to restart or clean the database, it tells the test utility to restart the server. Furthermore we should/could use truncate instead of a hard db reset.
I think both types of testing are important. Personally, routing tests are more important, because we ensure that Ghost works from a user perspective (e.g. also user flows, url behaviour). Even that they have the disadvantage that if a test fails it's harder to figure out the reason why the test failed, because it affects the whole system. But we have added better logging and since it's easier to find out the reason. But integration tests are important as well, as soon as we have to test connected components, which are easier to test with integration tests e.g. timezone changes and we expect a specific behaviour. But i agree, we overuse integration tests for e.g. model and api behaviour. Same for routing tests, we used to copy test cases to ensure all kinds of edge cases work. As both types are equally slow and if we can improve the speed of the routing tests, i would like to suggest that only one type tests the model/api layer. And personally i think the routing tests should cover that. All edge cases belong to unit tests if possible. I can think of the following rule:
Here is my suggestion for a task list: Each subtask allows to remove duplicated or unimportant tests. |
Agree on all of that 👍 So we have a plan to move forward in the tests 🎉 , have a plan is half the problem solved 😁 Back in the So the Note 1: this probably needs a bit more work on the API folder first, cos the stuff that's in |
refs #9178 * Add eslint deps, remove old lint deps * Add eslint config, remove old lint configs * Config for server and tests are different * Tweaked rules to suit us * Fix linting in codebase - lots of indent changes. * Fix a real broken test
@kirrg001 I removed the confusing image from the previous comment and very quickly moved everything around on a branch: Can take a look here: https://github.com/ErisDS/Ghost/tree/structure-spike/core/server Not suggesting it's perfect, but it's a rough idea. |
refs #9192, refs #9178 After trying to progress with current implementation, it became clear that the route service can't control the boot sequence, because then we end up with circular dependencies between the route service and the channel service. The route service now exposes: - a siteRouter - a way for apps to register routes. - ParentRouter base class for other modules to use - the registry ... - moved the default route setup back to site/routes.js 🙈 - moved the parent channel router back to the channel service (this makes way more sense imo) - this structure prevents circular dependencies - split the registry out into it's own thing - fixed-up various bits of tests and comments - DEBUG will print a list of routes 🎉
I'll work on the agreed test env improvements this and next week 👍 |
refs TryGhost#9178 - adapt major changes
refs TryGhost#9178 - adapt major changes - see https://github.com/shouldjs/should.js/blob/master/History.md - should.have.enumerable was removed
refs #9178 - Removed tests that had duplicated or already covered cases in acceptance or unit tests - Optimized some slow tests - Some test suite naming changes - Imports cleanup
I had a blog running on port 2369 and I was unable to run my tests anymore. I was trying to figure out for 10minutes why it's not working. There was no helpful debug output and I haven't received a proper error. Would be great if we could resolve this pain 🤣 |
After cleaning up redundant/slog tests, my current goal is to improve our regression test suite. After some analysis done yesterday here are the conclusions that came up with. API suite has rather comprehensible structure. Think it should follow similar setup and rules as acceptance tests but with more specific state setup. Will need to be converted once acceptance suite is reworked. Don't see a need to reinvent the wheel for them :) The rest of the suite has no clear structure and has a very different state setup/assertion techniques. For example, List of tests non-API suites and possible refactors:
|
Let's discuss this ^ on Friday 👍 |
@kirrg001 if it's ok, would be best to talk through it on Thursday morning your time as I'm flying on Friday 😉 |
We had a chat about the test env improvements and we realised that we want to much at once and we need to set smaller goals. Goals for next Monday
We will set tiny goals every week, which are achievable on a Monday. |
refs TryGhost#9178 - These test belong to knex/bookshelf
Had a stab at the reduction of model regression tests today. Was able to fairly easy port settings model suite into unit tests by mocking db access with Couple thoughts regarding a further reduction of posts model regression suite:
|
refs #9178 - Migrated settings model regression to unit tests - Removed redundant/unuseful post tests - Extracted post model regression tests to API tests - Renamed test suites for consistency
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Not stale |
refs #9178 - continue with killing our global utils folder - i haven't found any better naming for lib/promise - so, require single files for now - instead of doing `promiseLib = require('../lib/promise')` - we can optimise the requires later
refs #9178 - we could now also move any crypto usages to lib/security, but no priority - the main goal is to tidy up our utils folder
refs #9178 - first iteration of tidying up the unit tests - this is useful in the current stage, because if i move files in the server folder, i need a clean folder/file structure to detect which tests needs to move - this is a simple cleanup to reflect the current server folder structure
We have a few goals of restructuring the codebase that we have agreed on but aren't documented anywhere. This issue serves as a place to document what we plan to do & as a place to document new utils and concepts that are intended to make our lives easier and help us move faster.
Lib & Lib common
Add a new
lib
folder, to contain all of the shared libraries in Ghost.Underneath this, a new
common
folder, which contains the libraries that are used everywhere:These 4 things need to be exposed to the whole of Ghost including theme helpers, apps & adapters.
They are are all effectively "read only" things - it's not possible to affect behaviour by using these libraries.
Other things that might live under lib, would be an apps folder that contains all the code which manages apps, whereby the top level
apps
folder contains Ghosts built-in "internal" apps.Services
There is a second type/set of shared libraries in Ghost, which I would call "services". These cannot be exposed to apps/adapters/themes directly without creating security concerns or permissions problems:
In the near future this might also feature a new url and/or routing service.
Services might end up having some sort of registry in future.
Clearing up data
The data folder is a crutch. It's full of all kinds of weird stuff that has always needed a proper home. Not sure how we're going to move forward with the meta folder just yet, but we know this is a nightmare.
Many of the these things will get moved to services over time.
A fresh look at utils
We've bunged an awful lot of stuff in "utils" over the years. Some of it should be there, some of it should probably be in a service (url stuff). Some of it should belong TO a library or service, and some of it can be farmed out to either be a dependency or by using a new dependency.
Tests
We want to focus mainly on unit testing and either the route-based functional tests, or the integration tests. There's a whole bunch of tests which can/should be removed or replaced. The aim is to make tests FAST so we can ship FAST.
The utilities & fixtures around tests need to be similarly split up so that different types of test have different types of utilities, and that fixtures for specific bits of data or config are easier to find / write.
Where we have defined data structures, we can move towards using more custom should assertions - E.g. for testing that API responses or resources look how we expect them to look.
There's not going to be any one big push towards doing this, but it is expected that PRs and commits go by that make small movements towards these goals.
Rough task list
(so we know when we can close this)
Structure:
web
folder for all the expressy stuffTest refactoring:
Tools:
Ghost/core/server/api/webhooks.js
Line 17 in bffb3db
The text was updated successfully, but these errors were encountered: