This is the 21st day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021
Hello ~ I’m Milo! I am building an open source interface testing platform from 0 to 1, and I am also writing a complete tutorial corresponding to it. I hope you can support it. Welcome to pay attention to my public number test development pit goods, get the latest article tutorial!
review
We supported the Redis preconditions, but there is one particularly unfriendly aspect:
If the preconditions are close, I can’t even copy them.
It would be very unfriendly to choose one to copy quickly, just like the pre-case.
So we’re going to do that in this video.
rendering
As usual, here are the renderings:
Train of thought
It’s actually relatively simple for the back end to support this operation.
Fortunately, our backend Constructor has a type field that distinguishes the types of preconditions. So we just need to arrange a query interface:
Find out the details of the preconditions according to the type, and then select, the front end with a form to bring in, you can copy the entire preconditions.
Back end first
Write the query interface, show which case it belongs to, and give details of the preconditions.
The front end has the TreeSelect component identified, so the back end uses a two-tier data format:
[{"title": "Use cases"."key": "caseid"."children": [{"title": "Data constructor A"."key":
"constructor_id"}}]]Copy the code
Let’s build it
-
Write the ideas
I do not plan to use join(I have carried out this idea from the very beginning. I prefer to use two queries and join the data by myself. Actually, JOIN is not well used)We first check the preconditions of the corresponding type, and then we can get all the case_id, and then use case_id to check the case information, isn’t it beautiful?
The difficulty is how to form the tree, but actually the tree has only two layers. What we need to do is to assemble children first and then parent.
This is where defaultdict comes in.
- Check the preconditions that meet the conditions and save them to defaultdict based on case_id as key and value as preconditions
- Find the case name of case_id from defaultdict keys, iterate over it, piece together the parent, and place the value from Defaultdict into the children field.
Let’s look at the code:
@staticmethod
async def get_case_and_constructor(constructor_type: int) :
# finally return the result tree
ans = list(a)async with async_session() as session:
# where case_id => preconditions are mapped
constructors = defaultdict(list)
# select all preconditions according to the type of preconditions passed in
query = await session.execute(
select(Constructor).where(
Constructor.type == constructor_type,
Constructor.public == True,
Constructor.deleted_at == None))
# and put these preconditions in constructors
for q in query.scalars().all():
constructors[q.case_id].append({
"title": q.name,
"key": f"{q.id}"."isLeaf": True.Because trees usually only have name and ID, we need other data
"constructor_json": q.constructor_json,
})
Select * from case where preconditions exist
query = await session.execute(
select(TestCase).where(TestCase.id.in_(constructors.keys()), TestCase.deleted_at == None))
# Construct the tree, know that children have already built it, right inside the constructors
for q in query.scalars().all() :Add the use-case ID to the cs_list instead of the native JOIN
ans.append({
"title": q.name,
"key": f"case_{q.id}"."disabled": True."children": constructors[q.id]})return ans
Copy the code
Notes are written in great detail and every step is explained clearly.
Next comes the interface section, which needs no further explanation:
Get all data constructors
@router.get("/constructor/list")
async def list_case_and_constructor(constructor_type: int) :
try:
ans = await ConstructorDao.get_case_and_constructor(constructor_type)
return PityResponse.success(ans)
except Exception as e:
return PityResponse.failed(str(e))
Copy the code
The front-end adaptation
Front-end adaptation is as simple as adding a component and updating the form’s value when the component selects the value.
oh shit~~
Until now I realize THAT I have written similar code, sad = =
Sure enough, you’re going to fall in the same place, but I don’t think there’s any classification of the preconditions that I wrote before, so I’m going to have to modify it, or I’m going to write it this time as a V2 interface.
I have to say, the front end is a little bigger than expected. A closer look at the interface shows that the logic is:
- Find the corresponding precondition ID
- Query the preconditions and replace them
However, the previous interface is only for case types, so it is very weak.
We currently make it a new version of the ship for all of our types:
import {Col, Row, TreeSelect} from "antd";
import {connect} from 'umi';
import {useEffect} from "react";
const CopyTreeSelect = ({construct, dispatch}) = > {
const {constructorData.searchConstructor.constructorType} = construct;
const save = (data) = > {
dispatch({
type: 'construct/save'.payload: data,
})
}
const getConstructorData = () = > {
dispatch({
type: 'construct/getConstructorTree'.payload: {
constructor_type: constructorType}})}useEffect(() => { getConstructorData(); }, [constructorType])
return (
<Row style={{marginTop: 24, marginBottom: 24}}>
<Col span={3}/>
<Col span={18}>
<Row>
<Col span={4}/>
<Col span={20}>
<TreeSelect
allowClear
showSearch
style={{width: '100%'}}
value={searchConstructor}
filterTreeNode={(inputValue, treeNode) => {
return treeNode.title.toLowerCase().indexOf(inputValue.toLowerCase()) > -1
}}
dropdownStyle={{maxHeight: 600, overflow: 'auto'}}
treeData={constructorData}
placeholder="By searching for construction conditions, you can quickly copy parameters oh!"
treeDefaultExpandAll
onChange={(e) => {
save({searchConstructor: e})
if(e ! = =undefined) {
dispatch({
type: 'construct/getConstructorData',
payload: {id: e.split("_") [1]}})}else {
dispatch({
type: 'construct/save',
payload: {testCaseConstructorData: {type: constructorType, public: true, enable: true}},
})
}
}}
/>
</Col>
</Row>
</Col>
<Col span={3}/>
</Row>
)}export default connect(({loading, construct}) => ({loading, construct})) (CopyTreeSelect);
Copy the code
Separate this component out into a copy component. And automatically change the data source when the precondition type changes.
A few more tweaks on the page and you’re done. To tell the truth, this piece is a bit bloated, because I can’t see it, so I let go of myself first, but also let go of everyone.
In the next section, let’s take a stab at writing a simple test report email notification feature. (In fact, simple is not simple, if you want to design the style, but also very troublesome)