Comments (11)
I think in that way we are changing an apple by pear, it's the quit same thing of write my own test, I dont see so much value in use it, buuuuuut the ideia/proposal is awesome and I think we could to go beyond.
Once we have the entity's validation and we could to use it as metadata, we could to auto generate the basic usacase tests based on entitiy's validation. e.g:
entity('Product', {
id: id(Number),
name: field(String, {
validation: {
length: { minimum: 6 } ,
contains: { notAllowed: "hello world" }
} } )
})
const { CreateProduct } = require('./usecases/createProduct')
spec(CreateProduct, {
'Successful create a simple product': scenario({
description: 'Try to create a product with just a valid name.',
request: {
name: 'A simple product'
},
user: () =>
({ canCreateProduct: true }),
injection: () =>
({ ProductRepo: { save: () => { id: 1 } } })
'my super specific scenario': check((ret) => {
assert.ok(ret.product.name.lenght/2 * 8 !== 10000)
}),
}),
terminal output:
Runned the tests:
⚙️ Happy Path: true
- Successful create a simple product
🟢 must to have an id
🟢 must to have a valid name
🟢 name do not have "hello world"
⚙️ Happy Path: false
- Unsuccessful create a simple product
🟢 must to not return id for invalid entity
🟢 must to return an Err XXX if invalid name
🟢 must to return an Err YYY if name contains "hello world"
⚙️ Specific scenarios:
🟢 my super specific scenario
look, we have 6 tests auto-generated by herbs, I think this way we bring the Herbs idea of provide the things based on metadatas.
Other interesting scenario is when the usecase handle multiples entities, I could to generate test for all entities and combine all possible tests between then.
For now, I dont know how we could to know what is all entities the usecase handle, but I think this is the way.
from herbs.
@dalssoft First of all, I'd like to say that I think the idea is quite interesting, tests are really one of the things herbs hasn't reached yet.
I have some doubts and questions about the points mentioned:
1- A glue instead of a lib
Have you considered using a test library instead of creating your own? It seems to me that we can build this on top of something consolidated, like a connector (for example mocha). This would give us several benefits such as robustness, code coverage, reporting, shortening the learning curve, and not having to go to a part that herbs don't master.
2 - About Given / When / Then
How about we encapsulate the "3 magic words" in variables, just like we do with steps? I think it would be more readable, more reusable (for multiple entries), and also more declarative.
Example:
spec(ChangeItemPosition, {
'Successful change item position': scenario({
description: 'Try to change the item position in a list with a valid position.',
given = given(async (ctx) => {
request: {
itemId: 1,
position: 10
},
user: () =>
({ canChangePosition: true }),
injection: () =>
({
ListRepo: { find: (id) => ({ id, items: [] }) },
ItemRepo: { save: () => ({ position: 10 }) }
})
)}
when = when (async (ctx) => {
const uc = usecase(given.injection)
const hasAccess = await uc.authorize(given.user)
const response = await uc.run(given.request)
)}
then = then (async (ctx) => {
'Item position must have been changed and saved in the repository': check((ret) => {
assert.ok(ret.item.position === 10)
}),
'Item position must be in a valid range': check((ret) => {
assert.ok(ret.item.position >= 0)
assert.ok(ret.item.position <= 20)
})
})
})
Here I wouldn't make the when transparent, because that way you plaster the way the developer uses the code. For example, not every use case is authorized. Another point is that if you encapsulate the given, then and when at the metadata level, this can be very rich for the shelf
and for the herbarium
.
3 - About spies
I think what convinces me to create a library of our own is if we could actually look deeply here.
Example: connecting the audit with the test runner or knowing exactly which step of the use case broke the test or even performing specific validations in steps. But I think we can do it with glue still (I need to study more on the subject)
4 - About self-generated tests from Entities
I really like the @italojs idea, but I believe that Entities need to have their own test files, disconnected from use cases.
In my opinion, your idea does not conflict with @dalssoft idea, they are two different initiatives that can be matured in different topics because in my view both are valid.
from herbs.
I really think that ideas is great! I can see the value of an Aloe, especially for the business specialist if we add this to analyse the structure of the project into the Shelf...
Thinking about this documentation when we have different contexts in the same Use Case, we can define different contexts with the mocha, like context
or describe
...
What do you think of mantain some of these labels to improve the organization of tests?
Example, an UseCase with IfelseStep with bifurcation of the complex rules can use this to improve the view when we use this into the shelf and the terminal...
from herbs.
I think in that way we are changing an apple by pear, it's the quit same thing of write my own test, I dont see so much value in use it, buuuuuut the ideia/proposal is awesome and I think we could to go beyond.
@italojs, but the point is exactly that: the tests we write today (ex: with mocha or cucumber) are not part of the domain and can't export metadata
1- A glue instead of a lib
@jhomarolo maybe. I don't see much value on the runner. I may be not giving the importance due to the problem, but I don't see the runner as the complex part of the software. The complex part is to build the DSL, like we did with gotu and buchu
2 - About Given / When / Then
@jhomarolo it is something to be explored
4 - About self-generated tests from Entities
@jhomarolo agree
Example, an UseCase with IfelseStep with bifurcation of the complex rules can use this to improve the view when we use this into the shelf and the terminal...
@eacvortx could you elaborate on that?
from herbs.
New proposed syntax.
For Use Cases:
const { CreateProduct } = require('./usecases/createProduct')
const productSpec =
spec(CreateProduct, {
'Successful create a simple product': scenario({
description: 'Try to create a product with just a valid name.',
happyPath: true,
'Given a simple Product': given({
request: {
name: 'A simple product'
},
user: () => ({ canCreateProduct: true }),
injection: () => ({
ProductRepo: { save: () => { id: 1 } }
}),
}),
'Product must be saved in the repository': check((ret) => {
assert.ok(ret.product.id)
}),
'Product must have a new Id': check((ret) => {
assert.ok(ret.product.id === 1)
}),
}),
'Do not save a product with invalid name': scenario({
description: 'Reject products with invalid names in the repository',
'Given a invalid Product': given({
request: { name: 'A simple product @' },
user: () => ({ canCreateProduct: true }),
injection: () => { },
}),
'Product should not be saved in the repository': check((ret) => {
assert.ok(ret.product === null)
assert.ok(ret.isInvalidEntityError)
}),
})
})
For entities:
const { Project } = require('./entities/project')
const projectSpec =
spec(Project, {
'Successful create a valid Project': scenario({
description: 'Try to create a project with just a valid name.',
happyPath: true,
'Given a simple Project': given(() => {
return Project.fromJSON({
name: 'New project'
})
}),
'When check if is valid': when((product) => {
product.validate()
return product
}),
'Must be valid': check((product) => {
assert.ok(product.errors === {})
}),
}),
// *** Custom methods ***
'Successful generate a valid Project ID': scenario({
description: 'Try to create a project ID based on its name.',
happyPath: true,
'Given a simple Project': given(() => {
return Project.fromJSON({
name: 'New project'
})
}),
'When generate project ID': when((product) => {
return product.generateID()
}),
'Must be valid': check((ret) => {
assert.ok(ret === 'new-project')
}),
}),
})
Please, comment.
from herbs.
I liked the changes, especially the inclusion of reserved words. Perhaps the explicit inclusion of then
also makes sense.
I'm still finding it difficult to easily enable integrations with other tools that we normally use for CI (test coverage, reports, etc.). Do you believe that we will implement these functions or at some point make integrations with third-party tools?
from herbs.
I'm still finding it difficult to easily enable integrations with other tools that we normally use for CI (test coverage, reports, etc.).
Regarding test coverage, I'm not sure, but it seems the coverage tools [1] are agnostic to the test runner.
For others tools, what problems / issues do you expect to find?
[1] https://github.com/jaydenseric/coverage-node
from herbs.
This feature could be an alternative to implement aloe without create a test runner: nodejs/node#42325
from herbs.
To provide a great DX and a fast learn curve, we could work with context like usecases
'Given a simple Project': given((ctx) => {
ctx.product = Product.fromJSON({
name: 'New project'
})
return ctx
}),
'When check if is valid': when((ctx) => {
ctx.product.validate()
return product
}),
'Must be valid': check((ctx.product) => {
assert.ok(ctx.product.errors === {})
}),
}),
because sometimes I could put many instances inside the ctx instead only my principal entity
from herbs.
we could work with context like usecases
@italojs on the current implementation it ends up exactly like that:
from herbs.
Since Aloe has already landed on herbs and CLI as beta, I'm closing this issue. Any suggestions or improvements, please use Aloe repo.
from herbs.
Related Issues (20)
- New herb, complement a herb or use some market lib to transforms and conversions? HOT 6
- [CI] - Codecov deprecration of v1 HOT 1
- Create a XLSX spreadsheet glue from the output of an USECASE HOT 4
- Hard to identify the reason of an error HOT 5
- A suggestion to improve code generation HOT 3
- Blog posts suggestions HOT 3
- Add status badge in all repositories HOT 2
- Code owners feature HOT 1
- CLI - What would the future of a new CLI look like?
- New Glue - Herbs2memcached HOT 1
- Native queue support HOT 1
- New Glue - Herbs2Serverless HOT 1
- Live metrics - audit trail HOT 1
- How can we pass authentication/authorization data more implicitly? HOT 1
- Upgrade node version to 16.x HOT 1
- Herbs DB Migrations - Change your domain and your database will follow
- Enable intellisense in IDE HOT 1
- Implement Performance Measurement APIs from Node.js in AuditTrail for HerbsJS Framework HOT 1
- Typescript support And class-based Use Case
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from herbs.