Open ajaishankar opened 1 year ago
Hey @ajaishankar ! This is a really awesome proposal 👏👏. Very well written and really some very innovative ideas here (specially around param passing)
I feel we should discuss and ideate on this more before we get into implementation. Here are my comments.
Parameter passing across requests I really like the idea of updating variables from the json body of the response (like shown in the example request flow of login and profileUpdate). This is something we definitely need to implement in Bruno. Json query is cool and plays well with this idea.
Workflows as first class citizen (FCC) During the earlier days of development, I though that we need a second thing called as "testsuite" whose UX can be optimized to write tests, but as I pondered more on it, iI realised that a testsuite is nothing but a sequence of requests and collections already describe it. If we add a post script tab in the request panel, and the requests under the collection can be reordered, won't it pretty much be a workflow ? Let me know if you still see advantages of having workflows as FCC alongside collections. Its going to be a tradeoff. If we can implement the same thing in collections, then it might be better not to add it as a FCC
Workflows as subroutines inside tests Workflow is a nice word. As I perused your proposal, It occurred to me that workflow can be used to represent a group of requests that can called as a whole during writing tests.
Ex: Let's say your app is JIRA, and you wanted to write 10 tests. Typically in postman you would create 10 folders, and write steps inside them. Each test/folder had many steps that were common across them. You could actually group these common steps as "workflows" and have tests call them (kind of like a subroutine).
Is "collection" even the right abstraction ?
The proposal made me think, Is collection even the right abstraction. Should it be called "projects" instead (refer insomnia)
Below is a mock design of how workflows, tests and requests can exist inside a "collection/project"
In the future, we can add a new thing called "spec" that allows you to interactively design a swagger api spec
Scripting I think we need keep the option of scripting open for users who want to write custom scripts. I thought quite extensively on how to combine your idea of parameter passing while still keeping the possibility to write custom scripts. I have an idea which I will write in detail tomorrow.
Moving forward I think these are some good ideas, but these still need more examination. We don't need to get into a limbo until we ratify the concept of a workflow. We need to pick the smallest thing that makes absolute sense and does not tie us up into a certain structure, and implement it.
I feel we can implement your idea of updating variables based on response that can be subsequently used when running the next request. This feature seems fundamental. I have some thoughts on how this could be done with scripting. Will write it in detail tomorrow.
Again, fantastic proposal @ajaishankar . Made me think deeply. Let me know your thoughts. Feel free to voice disagreements and point out flaws in the line of thinking here.
Thanks @helloanoop
On collections vs workflows - saw this in the postman documentation.
https://learning.postman.com/docs/running-collections/building-workflows/
But the above looks like an afterthought. Whether we really need workflow as a FCC is debatable. But the distinction between a collection vs workflow is simply the fact that you cannot run an arbitrary step in a workflow whereas in a collection you can.
On scripting, I'd keep that as an option (for sure) for advanced users but the primary focus should be declarative imo.
If you see the Postman link above, outright they are looping and branching which is I feel is bad.
On tests the primary use case could be "black box testing" - run a workflow and verify the final json response matches what we expect.
Again we can pick and choose the values to assert using json-query.
Can login with correct credentials
{
"$res.data.user.name": "bruno"
}
Login should fail with incorrect credentials
{
"$res.status": 401
}
Throw in some query helpers similar to jest asserts (see isDefined below) and and you are well on the way to a nice zero code experience!
Can place order
{
"$res.data.order.items.length": 2,
"$res.data.orderNumber:isDefined": true
}
And if you really need complex logic when the final assertion is evaluated, we can pass say lodash to the context.
{
"_.filter($res.data.pets, p => p.name === 'bruno').length": 1
}
Whether we really need workflow as a FCC is debatable.
I feel we should have a single first class citizen which directly maps to a folder on the local filesystem. At the moment, it is a collection
, but I feel it has its limitation and something like project
might make more sense as we add more functionalities (workflows, tests, spec). One of the long term vision is that every api source code repository has a folder inside it which can be opened in bruno.
├── src
│ ├── main
│ └── test
├─ .bruno
├─ pom.xml
On scripting, I'd keep that as an option (for sure) for advanced users but the primary focus should be declarative imo.
I agree with this.
While we wait to see how the concept around workflows plays out, I feel confident in the approach towards assertions you mentioned. I think we can add an Assert
tab in the request for the user to write the assertions, and an Assert
tab in response to display the assertions result. We will add a Scripts
tab later for the user to write custom scripts if they want.
This seems fundamental to in the request builder. What do you think ?
Love the long term vision of having a .bruno folder in the source code!
The UI looks good, but just one question:
Would it make sense to have the Assert configuration only in the right hand pane?
Would it make sense to have the Assert configuration only in the right hand pane? The right hand pane (response pane) only becomes visible after the response arrives
Also we can show the actual values side by side in that Assert tab itself... Not able to visualize the side by side in Assert tab given that right hand pane becomes active after response arrives
@ajaishankar it'd be great if you want to take a stab at implementing this, I feel we are both aligned here on the assertions part. I was thinking we will use the request tab to code the assertions, and the response tab to show the assertion results (kind of like of how postman allows to write scripts in request pane, and displays test results in response pane).
Got it! Yes I'll take a stab at implementing this... 👍
@helloanoop put more thought into workflows and looks like we need not make it into a FCC!
Turns out the current abstraction of collections and requests will suffice.
Here is a reference workflow implementation using collection variables. Demo
The data picked up from the the response of the first request becomes input for another request in the collection.
The difference from Postman is the data dependencies are declaratively specified and easy to reason about.
https://github.com/ajaishankar/bruno-vars
Let me know what you think...
@ajaishankar Slick demo! Appreciate the time you put in to create the demo.
Onboard with the approach of declaratively specifying the data dependencies in vars.
So, this leads us to specifying var definitions in the request pane (left hand pane) right ?
Am I visualising this correctly ?
Currently bruno has env variables (similar to postmans env variables concept). Note: Postmans envs are global (although they also support collection vars). Bruno env vars are co-located in the collection by design. I am thinking we should keep both, env vars that are meant to be used to switch values b/w envs And "vars" (kind of like collection vars), that can be defined inside requests to be evaluated before sending request, and after receiving response.
Thanks @helloanoop
Yes your visualization is correct 👍 vars are declared in the request pane as in your screenshot (which btw looks far better than my horrible attempt at UI 😃)
Just to summarize:
This is the Postman collection var docs.
https://learning.postman.com/docs/sending-requests/variables/
Where I feel our approach shines is everything being declarative, and being able to track inter request dependencies. For example some var set in request one is used in request five...
Hey @ajaishankar
Had taken some time off from the project. I am back again at it. The flow you mentioned in points 1-8 looks good.
I think we are at a good place to get start implementation on this. I feel, we can build this functionality incrementally and tackle small issues on the way. Here is my suggestion on breaking up the implementation
Lets add a tab called Vars
in the request pane, and to begin with we will put vars static values and make the request body/url/headers pick this up and use it. In case of conflicting var names w.r.t. env vars, the request vars gets precendence
Lets add the functionality to to support response vars. i.e vars having as $res.data.id
This brings us to the question, how do we know if a var is a response var ?
Are there issues in evaluating all vars (before and after request) ?
Another important thing to note is that currently, there is no concept of a session in bruno, and currently ordering/sorting requests within the collections is not possible. I am currently working on it. This should be ready in a week's time. What I am to get done is to initially support ordering requests based on drag-n-drop and then support option to run a collection / folder within the collection.
Sorry for late response... on question 2 on how we know if a var is a response var?
Postman has a list of dynamic vars, and for us similarly $res
is a special var checked here.
Any expression that refers to $res
should be evaluated after a response, others before request...
@ajaishankar Have added a new ticket to track how proposals would work as per the latest bru lang spec #87
This is a proposal for implementing workflows in Bruno.
Somewhat related to Bruno Test Script RFC #46
Workflows:
Examples:
A workflow would be a first class concept in Bruno similar to collections.
Defining a workflow is simple enough, but how do we pass variables over is the interesting part of this proposal.
In Postman after an API call we can run a "post request script" to set collection variables, which are then reused in rest of API calls. But usually it is difficult to understand what the script does, what variables are set, since these are well... scripts :)
Workflow implementation
The idea is... look ma, no scripts!
Update profile workflow steps
Tests:
Everything being simple json provides a lot of benefits and opportunities.
@helloanoop I can do a PR if this is something you'd be interested in.