Use Pytest Cache Fixture to implement test result caching

During the process of automatically closing the interface, we often encounter scenarios such as "Request 2 needs to use the data responded to Request 1". The common approach is to make use case dependencies or write the response results of Request 1 to a file. When used Read the file. Of course, this is not the focus of this article. This article mainly introduces cachewriting and reading cache data.

request.config.cache

Students who don’t understand it yet request fixturecan read the article written by me first.

Let’s look at the use case first:

def test_01(cache):
    cache.set("token", "uiouoouoiou")
​
def test_02(cache):
    r = cache.get("token", None)

test_01In this way, the value will be cached when the code is executed token, and the value test_02can be read from the cache at any time of execution token. How is that Cacheachieved? Let's take a look at the source code. Direct access to source code

Implementation principle

def test_01(cache):
    cache.set("token", {"token": "1212121"})

We cache.set()make a breakpoint on this line. debugAfter execution, debugthe result is

cache = Cache()
_CACHE_PREFIX_DIRS = 'd'
_CACHE_PREFIX_VALUES = 'v'
_cachedir = /PycharmProjects/panda-test/org/.pytest_cache
_config = <_pytest.config.Config object at 0x109e80d60>

You can see that a cache instance is automatically created and some data is initialized. By default, the cache file should be in the .pytest_cachedirectory

/_pytest/cacheprovider.py

@fixture
def cache(request: FixtureRequest) -> Cache:
    """Return a cache object that can persist state between testing sessions.
​
    cache.get(key, default)
    cache.set(key, value)
​
    Keys must be ``/`` separated strings, where the first part is usually the
    name of your plugin or application to avoid clashes with other cache users.
​
    Values can be any object handled by the json stdlib module.
    """
    assert request.config.cache is not None
    return request.config.cache

As you can see, cachewhat is returned is Cachean object. Let’s see Cachehow the object is implemented.

    def set(self, key: str, value: object) -> None:
        path = self._getvaluepath(key)
        try:
            if path.parent.is_dir():
                cache_dir_exists_already = True
            else:
                cache_dir_exists_already = self._cachedir.exists()
                path.parent.mkdir(exist_ok=True, parents=True)
        except OSError:
            self.warn("could not create cache path {path}", path=path, _ispytest=True)
            return
        if not cache_dir_exists_already:
            self._ensure_supporting_files()
        data = json.dumps(value, ensure_ascii=False, indent=2)
        try:
            f = path.open("w", encoding="UTF-8")
        except OSError:
            self.warn("cache could not write path {path}", path=path, _ispytest=True)
        else:
            with f:
                f.write(data)

This source code is used to save key-value pairs into the cache. The code is relatively simple, please explain briefly.

  1. Get the path of the key-value pair to be saved: Get the path ( ) of the value ( ) in the cache _getvaluepath()based on the given key ( ) by calling the method. The path here is a string separated by different levels, usually the first name is the name of the plugin or application.keyvaluepath/
  2. Check whether the path exists: Determine whether the path needs to be created by judging whether the parent directory of the path is a directory. If the parent directory already exists, it cache_dir_exists_alreadyis set to True; otherwise, it checks if the cache directory exists and if the cache directory already exists, it is cache_dir_exists_alreadyset to True, otherwise it creates the cache directory.
  3. Ensure that the supporting files exist: If the cache directory is newly created, call _ensure_supporting_files()the method to ensure that the supporting files exist. This method may be used to create other cache-related files or directories.
  4. Serialize the data and write it to a file: valueSerialize the value ( ) using JSON format to ensure it is a basic Python type or contains nested types (such as lists and dictionaries). Then, try to open the file corresponding to the path (encoded using UTF-8) and write the serialized data to the file.
    def get(self, key: str, default):
        
        path = self._getvaluepath(key)
        try:
            with path.open("r", encoding="UTF-8") as f:
                return json.load(f)
        except (ValueError, OSError):
            return default

This source code is used to obtain the value of the specified key from the cache. Here is a brief explanation:

  1. Get the path to get the value: Get the path of the value in the cache ( ) _getvaluepath()based on the given key ( ) by calling the method. The path here is a string separated by different levels, usually the first name is the name of the plug-in or application.keypath/
  2. Attempts to read a file and return cached values: open the file with the path (encoded in UTF-8) and json.load(f)load the data in the file as a Python object using . The loaded value is then returned.
  3. ValueErrorHandling exceptions: If the contents of the file cannot be parsed into valid JSON data or opening the file fails, exceptions ( and ) are caught OSErrorand the default value ( default) is returned.

I still learned a novel way of writing here, which I have never used before, which is with path.open("r", encoding="UTF-8") as f:equivalent toopen(path, "r", encoding="UTF-8")

These are two commonly used methods. Of course, there are more methods provided. Here is a brief introduction:

  1. __init__(self, cachedir: Path, config: Config, *, _ispytest: bool = False) -> None

    • Initialization method, used to set the properties of the class _cachedirand _config.
  2. for_config(cls, config: Config, *, _ispytest: bool = False) -> "Cache"

    • Class method that creates and returns an instance based on given configuration information Cache.
    • If the configuration item cacheclearis set to Trueand the cache directory exists, call clear_cachethe method to clear the cache.
    • Finally, a new Cacheinstance is returned.
  3. clear_cache(cls, cachedir: Path, _ispytest: bool = False) -> None

    • Class method, clear the subdirectories under the cache directory.
    • Build a subdirectory path based on the parameter cachedirand rm_rfdelete the directory recursively using the function.
  4. cache_dir_from_config(config: Config, *, _ispytest: bool = False) -> Path

    • Static method, obtains the path of the cache directory from the given configuration information.
    • First get the string representation of the cache directory from the configuration, then use resolve_from_strthe function to parse it Pathand return it as an object.
  5. warn(self, fmt: str, *, _ispytest: bool = False, **args: object) -> None

    • A way to issue cache warnings.
    • Use warnings.warnthe function to issue a warning message and specify the warning type PytestCacheWarning.
    • If the parameter is present args, it is used as a formatting parameter replacing the placeholder in the format string.
  6. mkdir(self, name: str) -> Path

    • Create a directory path object and create the directory under the cache directory.
    • Parameter nameis the name of the directory to be created.
    • Checks whether the directory name contains a path separator /and throws an exception if so.
    • Use _cachedir.joinpaththe method to build the full directory path, and mkdirthe method to create the directory.
    • Returns the created directory path object.
  7. _getvaluepath(self, key: str) -> Path

    • Generates the path to the value file based on the given key.
    • Build the value file path in the cache directory, using _CACHE_PREFIX_VALUESas subdirectory prefix.
  8. _ensure_supporting_files(self) -> None

    • Create support files in the cache directory.
    • Create README.mda file describing the purpose of the cache directory.
    • Create .gitignorethe file, ignoring all files in the cache directory.
    • Create CACHEDIR.TAGa file that marks the cache directory.

at last

cacheThe function is still very practical, such as the login function, which can be written to the cache after logging in token, so that when making other interface requests, it can tokenbe obtained directly from the cache when needed token.

Finally: The complete software testing video tutorial below has been compiled and uploaded. Friends who need it can get it by themselves [guaranteed 100% free]

Software Testing Interview Document

We must study to find a high-paying job. The following interview questions are from the latest interview materials from first-tier Internet companies such as Alibaba, Tencent, Byte, etc., and some Byte bosses have given authoritative answers. After finishing this set I believe everyone can find a satisfactory job based on the interview information.

Guess you like

Origin blog.csdn.net/wx17343624830/article/details/132838577