Hello ~ I'm Milo!
I'm building an open source interface testing platform from 0 to 1, and I'm also writing a complete set of corresponding tutorials. I hope you can support me.
Welcome to my official account test development pit, get the latest article tutorial!
review
In the last section, we played a wild game and solved the problem of repeated execution of APScheduler. In the previous section, we have written the online execution function of Redis.
In this section, we have to apply it to the preconditions.
Achievement display
Because bloggers code first and then write articles. Therefore, we can show the results. Today's changes are as follows:
- Preconditions (REDIS type) are supported
thinking
Preconditions to support Redis, the idea is actually very simple, and the mode is similar to SQL. So we can copy the SQL code.
Before, our executors were placed under the utils package, which is actually very unfriendly. In order to show professionalism, I decided to pull the Executor from utils and put it under the new directory core.
The core directory is intended to put some core methods of use case execution. Let's wait and see.
How to modify a file without affecting other data
This requires the great pycham. In fact, after we create a new core directory, we can directly move the executor.py to the core directory.
Moving files through pycharm is not only as simple as moving files, but also helps you deal with the packages introduced into this file. If the path changes, it will automatically help update. If other files reference executor.py, it will also help you update.
With such a powerful ide as support, I can play at will.
Split Executor
With more and more case execution logic, our executor.py can't hold. It's not that a py file can't hold 1000 lines of code, but we don't need to make it so bloated.
What we can remove most is the function that executes the construction method. First, we have several fixed construction methods. Let's see how we write when we only support sql and use cases:
async def execute_constructor(self, env, index, path, params, req_params, constructor: Constructor): if not constructor.enable: self.append(f"current path: {path}, Construction method: {constructor.name} Closed, Do not proceed") return if constructor.type == 0: try: data = json.loads(constructor.constructor_json) case_id = data.get("case_id") testcase, _ = await TestCaseDao.async_query_test_case(case_id) self.append(f"current path: {path}, The first{index + 1}Strip construction method") # The description is case executor = Executor(self.logger) new_param = data.get("params") if new_param: temp = json.loads(new_param) req_params.update(temp) result, err = await executor.run(env, case_id, params, req_params, f"{path}->{testcase.name}") if err: raise Exception(err) if not result["status"]: raise Exception(f"assertion failure , Assertion data: {result.get('asserts', 'unknown')}") params[constructor.value] = result # await self.parse_params(testcase, params) except Exception as e: raise Exception(f"{path}->{constructor.name} The first{index + 1}Constructor execution failed: {e}") elif constructor.type == 1: # The description is an sql statement try: self.append(f"current path: {path}, The first{index + 1}Strip construction method") data = json.loads(constructor.constructor_json) database = data.get("database") sql = data.get("sql") self.append(f"The current construction method type is sql, Database name: {database}\nsql: {sql}\n") sql_data = await DbConfigDao.execute_sql(env, database, sql) params[constructor.value] = sql_data self.append(f"The current constructor returns a variable: {constructor.value}\n Return value:\n {sql_data}\n") except Exception as e: raise Exception(f"{path}->{constructor.name} The first{index + 1}Constructor execution failed: {e}")
It can be seen that only two methods are very bloated. In fact, for a more readable writing method, we need to disassemble several construction methods. After disassembly, there is a run method respectively. In this way, we only need to judge the type and execute the corresponding run method.
New abstract base class
from abc import ABC from app.models.constructor import Constructor class ConstructorAbstract(ABC): @staticmethod def run(executor, env, index, path, params, req_params, constructor: Constructor, **kwargs): pass
The base class method is similar to the abstract class of Java. It defines a class and cannot be instantiated without implementing the methods inside.
- sql implementation
- testcase implementation
There are some complex changes in test cases:
Generally speaking, we call the run method of preconditions by case, but what happens because the test case needs to call the executor again?
The executor refers to testcase and the executor refers to a loop, which is prohibited in python. After all, you're cheating!
So the method adopted here is to pass my Executor class as a parameter == (enough soil)
-
redis implementation
In fact, we have written similar methods when implementing redis, but before redis was executed according to id, now we need to change it and execute it according to name.
The implementation according to name is a bit of a last resort, mainly because our case is written to adapt to multiple environments. If the id is passed in, redis corresponds to the configuration of a fixed environment and cannot adapt to multiple environments.
Like sql, we use env+name to determine the redis connection (the name remains unchanged, and the redis connection becomes dynamic when env switches)
redis needs to change the following command:
The parameters passed in here are not just ID. when you pass in id=xx, you query according to ID, and when you pass in name=xxx, you query according to name, which is compatible with the online redis interface.
executor CLOSEOUT
Final effect
It seems clear at a glance. In fact, it is a bit like interface and impl.
That's all for today ~ we haven't figured out what to do in the next wave. We may improve the post conditions or execute case online or qiniu cloud oss. There's a long way to go. It's already 83 knots.
Online experience: http://test.pity.fun
If you like, you can give Pitty a star. Oh, your star is my motivation ==