python_测试_异步库插件asyncio

在python的测试中,如果实际的代码中有异步的代码,如果单纯的调用代码是会出现报错的问题。
需要在测试代码中添加插件pytest-asyncio,这是一个专注于进行异步测试的pytest的插件。

1 安装

根据官网的连接:pytest-asyncio · PyPI
在终端下载对应的库: $ pip install pytest-asyncio
在测试代码方法上添加注解: @@pytest.mark.asyncio

2 使用

具体的使用办法可以参见以下代码:

@pytest.mark.asyncio
async def test_some_asyncio_code():
    res = await library.do_something()
    assert b"expected result" == res

3 案例

在不同的测试场景中,都是能使用到插件的。

3.1 在同一事件loop中运行class中的所有测试

所有测试都可以通过使用pytest.mark.asyncio(scope =“ class”)标记在同一事件循环中运行。通过使用Asyncio标记作为类装饰器,可以很容易地实现这一点。

import asyncio

import pytest

@pytest.mark.asyncio(scope="class")
class TestInOneEventLoopPerClass:
    loop: asyncio.AbstractEventLoop

    async def test_remember_loop(self):
        TestInOneEventLoopPerClass.loop = asyncio.get_running_loop()

    async def test_assert_same_loop(self):
        assert asyncio.get_running_loop() is TestInOneEventLoopPerClass.loop

3.2 在同一事件loop中运行module中的所有测试

所有测试都可以通过使用pytest.mark.asyncio(scope =“ module”)标记在同一事件循环中运行。通过向您的模块添加pytestmark语句可以轻松实现这一点。

import asyncio

import pytest

pytestmark = pytest.mark.asyncio(scope="module")

loop: asyncio.AbstractEventLoop

async def test_remember_loop():
    global loop
    loop = asyncio.get_running_loop()

async def test_assert_same_loop():
    global loop
    assert asyncio.get_running_loop() is loop

3.3 在同一事件loop中运行包装中的所有测试

所有测试都可以通过使用pytest.mark.asyncio(scope =“ package”)标记在同一事件循环中。将以下代码添加到测试包的__init__.py:

请注意,此标记不会传递给子弹中的测试。子包构成了自己的单独包装。

import pytest

pytestmark = pytest.mark.asyncio(scope="package")

3.4 在同一事件循环中进行会话中的所有测试

所有测试都可以通过使用pytest.mark.asyncio(scope =“ session”)标记在同一事件循环中运行。标记所有测试的最简单方法是通过pytest_collection_modifyitems挂钩在您的测试套件的根文件夹中的conftest.py。

import pytest

from pytest_asyncio import is_async_test

def pytest_collection_modifyitems(items):
    pytest_asyncio_tests = (item for item in items if is_async_test(item))
    session_scope_marker = pytest.mark.asyncio(scope="session")
    for async_test in pytest_asyncio_tests:
        async_test.add_marker(session_scope_marker, append=False)

3.5 使用不同的事件循环测试

参数化event_loop_policy灯具参数参数所有异步测试。下面的示例会导致所有异步测试多次运行,一次在固定框架参数中为每个事件循环运行:

import asyncio
from asyncio import DefaultEventLoopPolicy

import pytest

class CustomEventLoopPolicy(DefaultEventLoopPolicy):
    pass

@pytest.fixture(
    scope="session",
    params=(
        CustomEventLoopPolicy(),
        CustomEventLoopPolicy(),
    ),
)
def event_loop_policy(request):
    return request.param

@pytest.mark.asyncio
async def test_uses_custom_event_loop_policy():
    assert isinstance(asyncio.get_event_loop_policy(), CustomEventLoopPolicy)

3.6 events事件

参数化event_loop_policy 参数参数所有异步测试。下面的示例会导致所有异步测试多次运行,一次在固定框架参数中为每个事件循环运行:

如果您只希望测试的一个子集与不同的事件循环一起运行,则可以选择将fixture的范围限制为包、模块或类。

import asyncio
from asyncio import DefaultEventLoopPolicy

import pytest

class CustomEventLoopPolicy(DefaultEventLoopPolicy):
    pass

@pytest.fixture(
    scope="session",
    params=(
        CustomEventLoopPolicy(),
        CustomEventLoopPolicy(),
    ),
)
def event_loop_policy(request):
    return request.param

@pytest.mark.asyncio
async def test_uses_custom_event_loop_policy():
    assert isinstance(asyncio.get_event_loop_policy(), CustomEventLoopPolicy)

3.7 如何对uvloop进行测试

RedeFinig event_loop_policy固定装置将参数所有异步测试。以下示例会导致所有异步测试多次运行,一次在固定夹参数中为每个事件循环进行一次:替换您的conftest.py中的默认事件循环策略:

如果您只希望使用UVloop运行测试的子集,则可以选择将固定装置的范围限制为包装,模块或类。

import pytest
import uvloop

@pytest.fixture(scope="session")
def event_loop_policy():
    return uvloop.EventLoopPolicy()

3.8 如何判断函数是不是为异步

使用pytest_asyncio.is_async_item来确定测试项目是否是异步和由pytest-assyncio管理的。

from pytest_asyncio import is_async_test

def pytest_collection_modifyitems(items):
    for item in items:
        if is_async_test(item):
            pass

4 注意

这个插件也有自己的问题:
它不支持标准联合库的测试类。建议用户使用UnitTest.isolatedAsynciotestcase或异步框架(例如异步)。

本文作者:redtea 红茶的博客
本文链接:https://redtea.top/16964281020029.html
版权声明:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可,非商业转载及引用请注明出处(作者、原文链接),商业转载请联系作者获得授权。

2024/04/14 posted in  开发技术

TypeScript的严格语法限制解决方案

在进行vue的开发中,在写ts文件时候,遇到有这么一个报错。经过查阅资料和实际进行解决,问题就是出现在了这个语法的严格造成的。

1 报错

具体报错信息如下:
image.png

2 缘由

更严格的类属性检查
TypeScript 2.7引入了一个新的控制严格性的标记 --strictPropertyInitialization

使用这个标记会确保类的每个实例属性都会在构造函数里或使用属性初始化器赋值。 在某种意义上,它会明确地进行从变量到类的实例属性的赋值检查

3 解决办法

找到文件中的tsconfig.json配置文件,增加或者修改配置 将严格初始初始化属性去掉
 "strictPropertyInitialization": false,

image.png

参考链接 :

本文作者:redtea 红茶的博客
本文链接:https://redtea.top/16964281020029.html
版权声明:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可,非商业转载及引用请注明出处(作者、原文链接),商业转载请联系作者获得授权。

2024/02/12 posted in  开发技术

nginx报错413的解决流程

最近在处理项目问题的时候,遇到了有这么一个有趣的问题,不像其他的报错401、502、500 等,这直接报错了413,这在开发中是常见有不常见的一个状态码,代表着这在使用中有nginx上的问题。

1 nginx报错413

1.1 问题显示:

nginx 出现413 Request Entity Too Large
界面中添加了对应的图纸数据,点击保存,调用更新接口,数据中数据实体过多

1.2 问题排查

  • 在网页出现错误的时候,首先就是查看请求日志,做问题复现
  • 查询运行日志

1.3 原因

nginx在做代理时候,对实际的数据转发有默认的限制,限制大小为1mb,这个可以在配置文件中进行修改

1.4 解决办法

  • 找到nginx配置文件 一般默认的路径是在/etc/nginx/nginx.conf
  • 使用vi或者vim命令打开文件进行修改 ,英文模式下,按住i键进入编辑模式
  • 找到其中的http{}模块,模块中添加client_max_body_size 20m; ,数字可以根据实际情况自定义,esc退出编辑,:wq ,退出保存数据
  • 重启nginx ,sudo systemctl restart nginx

1.5 附录

pgsql中查询数据大小:

SELECT id, DATA->>'name' AS filename , length(DATA::TEXT)/ 1024 AS leMB
FROM tablename
WHERE username= 'admin'
ORDER BY leMB DESC ;

修改参数:
5214bac6584a3c894e8bacd41344f0f.png

结语

在遇到问题的时候,不着急,先看看报错日志,确定问题的位置,更好的能解决问题。

本文作者:redtea 红茶的博客
本文链接:https://redtea.top
版权声明:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可,非商业转载及引用请注明出处(作者、原文链接),商业转载请联系作者获得授权。

2024/01/12 posted in  开发技术

lombok boolean属性缺失get set 方法

场景:使用Lombok时,发现对于

解决方案:使用包装类型即可Boolean

使用的场景

在实际的项目中,有使用到lombok插件,这个插件能减少写代码的时候,不断的习重复的get、set方法,让代码变得简洁。

问题

俗话说,有便利的地方,必然会牺牲一部分东西作为交换的,同样,在在这个lombok也是如此,在进行相关操作的时候。
有遇到是boolean基础属性,会无法调用getset方法。
这是由于boolean的属性以isXXX开头时,会导致Lombok不会为该属性生成getXXXsetXXX方法,这是由于Lombok特性所致,具体原因可以见其官网说明。

解决方法

有两种办法进行解决:
一是使用包装类型Boolean。
二是手动对boolean设置get set方法。

结语

代码的世界是有趣的,时常会出现一些有趣的BUG,让人防不胜防,只能不断的精进自己,去了解他们。

本文作者:redtea 红茶的博客
本文链接:https://redtea.top
版权声明:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可,非商业转载及引用请注明出处(作者、原文链接),商业转载请联系作者获得授权。

2023/08/12 posted in  开发技术

Scala语言函数式编程数组转换错误

在使用scala函数式编程语言写对应的代码的时候,使用数组相关的知识,出现了转换的错误,不能正确输出对应的数组内容。

1 问题:

代码:

//多维数组  
val a17 = Array.ofDim[String](2, 2)  
for (i <- 0 to 1) {  
  for (j <- 0 to 1) {  
    a17(i)(j) = (i + j).toString  
  }  
}  
println("a17多维数组是:" + a17)
//正确方式
println("a17的正常显示数组为:" + stringOf(a17))

输出的结果是:
a17多维数组是:[[Ljava.lang.String;@77b52d12
对这个结果的解释是:

“[” 表示一维数组  
"[["表示二维数组  
"L"表示一个对象  
"java.lang.String"表示对象的类型  
"@"后面表示该对象的HashCode

2 解决办法:

1、直接在对应的数组后面跟上一个方法,Array.toString(x),就能将对应的数组显示出来了。
2、导入一个打印美化包
import scala.runtime.ScalaRunTime.stringOf
在引包以后,调用stringOf(x) 方法,就能实现对数组的打印了 ,这个方法对多维数组也是生效的。
3、使用mkString 方法,这个对一维数组是有效的,多维数组不能生效,使用方法 x.mkString(",")

本文作者:redtea 红茶的博客
本文链接:https://redtea.top/16964281020029.html
版权声明:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可,非商业转载及引用请注明出处(作者、原文链接),商业转载请联系作者获得授权。

2023/07/12 posted in  开发技术

asar文件的解压读取

在实际开发中,有这样子的需求,就是需要解压asar结尾的文件。这里会涉及到两个基础环境的安装,node.js和npm有对应的配置。
在本次的实验中使用的配置如下:
node版本:18
npm版本:10.0.1

1 网上教程

app.asar文件是Electron加密打包时的中间产物,electron.exe调用resources文件夹下的app.asar从而实现不用解压缩而直接读取文件内容的高效。

在网上的一些教程中,对asar文件的解压和打包主要是执行以下命令:

1、安装asar 
npm install -g asar
2、cmd窗口中解压文件
asar extract app.asar ./app
3、没有表示成功
在文件夹系统中可以查看

2 报错提示

执行安装命令中,实际会报错以下消息:

npm WARN deprecated [email protected]: Please use @electron/asar moving forward. There is no API change, just a package name change

原因是在新版本的框架中,已经有包含了asar的支持,不需要在额外下载对应的模块,只需要更更换执行的命令即可。

根据警告消息所示,官方建议改用 @electron/asar。这是一个针对 Electron 应用程序中的数据和文件管理的模块,它支持读取和打包应用内的文件,可以在命令行中使用。 您可以按照下面的步骤来更新 asar 版本:

1. 卸载旧版 asar: `npm uninstall asar`
2. 安装新版 @electron/asar: `npm install -g @electron/asar`
3. 使用 @electron/asar 打包应用程序: `npx asar pack <app_directory> <output_file>` 
4. 读取 asar 文件: `npx asar extract <input_file> <output_directory>`

3 执行成功

按照上一步的操作,更换了执行命令以后,就能正常把文件解压。

所以,在执行软件的使用中,有时候需要注意版本更换以后带来的问题,及时调整对应的执行和使用命令。

本文作者:redtea 红茶的博客
本文链接:https://redtea.top
版权声明:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可,非商业转载及引用请注明出处(作者、原文链接),商业转载请联系作者获得授权。

2023/06/12 posted in  开发技术

Apache Log4j Java 日志组件详解

前言:
Log4j 是 Apache 的一个开放源代码项目,通过使用 Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI 组件、甚至是套接口服务 器、NT 的事件记录器、UNIX Syslog 守护进程等;

我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。

最令人感兴趣的就 是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

1 主要的组件

Log4j有三个主要的组件:
loggers: 负责捕获日志信息 ,即日志纪录器,控制日志的输出以及输出级别(JUL做日志级别用Level类)
appenders: 负责输出信息到不同的目的地 ,即输出日志到指定的地方
layouts: 负责使用不同的样式输出日志,即格式化日志

1.1 日志级别

例如DEBUG、INFO、WARN、ERROR…级别是分大小的,
DEBUG < INFO < WARN < ERROR,可以用来代指该日志的重要程度,可以由这个来设置对应的。
image.png

1.2 日志输出位置

日志输出的位置是由参数appender决定的,根据不同的参数设定,可以将日志文件自定义输出到控制台、文件中等

- 常用Appenders:
    - ConsoleAppender  
        将日志输出到控制台
    - FileAppender 
        将日志输出到文件中
    - DailyRollingFileAppender (根据天数来对新日志文件的创建)  
        将日志输出到一个日志文件,并且每天输出到一个新的文件
    - RollingFileAppender (根据大小来对新日志文件的创建)  
        将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件改名,同时产生一个新的文件
    - JDBCAppender 
        把日志信息保存到数据库中

1.3 日志格式化

在日志输出中,用户可以根据自己的实际需求,把对应的日志按照自己的想法和格式进行输出,在Layouts给用户提供四种日志输出样式。

  • 根据HTML样式

  • 自由指定样式

  • 包含日志级别与信息的样式

  • 包含日志时间、线程、类别等信息的样式

  • 常用Layouts:

    • HTMLLayout
      格式化日志输出为HTML表格形式
    • SimpleLayout
      简单的日志输出格式化,打印的日志格式如默认INFO级别的消息
    • PatternLayout
      最强大的格式化组件,可以根据自定义格式输出日志,如果没有指定转换格式, 就是用默认的转换格式

案例使用:

- %m 输出代码中指定的日志信息
- %p 输出优先级,及 DEBUG、INFO 等
- %n 换行符(Windows平台的换行符为 “\n”,Unix 平台为 “\n”)
- %r 输出自应用启动到输出该 log 信息耗费的毫秒数
- %c 输出打印语句所属的类的全名
- %t 输出产生该日志的线程全名
- %d 输出服务器当前时间,默认为 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日 HH:mm:ss}
- %l 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如:Test.main(Test.java:10)
- %F 输出日志消息产生时所在的文件名称
- %L 输出代码中的行号
- %% 输出一个 “%” 字符  
    可以在 % 与字符之间加上修饰符来控制最小宽度、最大宽度和文本的对其方式。 
    如:  
    %5c 输出category名称,最小宽度是5,category<5,默认的情况下右对齐  
    %-5c 输出category名称,最小宽度是5,category<5,"-"号指定左对齐,会有空格  
    %.5c 输出category名称,最大宽度是5,category>5,就会将左边多出的字符截掉,<5不  
    会有空格  
    %20.30c category名称<20补空格,并且右对齐,>30字符,就从左边交远销出的字符截掉

1.4 项目使用情况说明:

输出日志使用是DailyRollingFileAppender,会每天生成日志。
==优化点:== 目前项目中有实时库的存在,写日志会很多,导致当日日志文件也会很大,查看日志的时候会存在打开困难的情况,可以考虑使用按大小创建日志比如300MB创建一个新的,给一个新的命名。

输出级别:
目前的级别是在debug info warn error 这几个级别中
分为两个目录写日志 debug_log 、 error_log 这两个,error中写的是info最小的,debug中写的是debug最小的。
==优化点:== 两个日志写入内容有重复,
1、可以在控制层对日志进行整理处理,分别在不同的地方写入不同的日志。
2、规划重要耗时做debug处理,其他警告、报错信息放到error中去。

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE log4j:configuration PUBLIC  
  "-//APACHE//DTD LOG4J 1.2//EN" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">  
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">  
  
    <appender name="A_ERROR" class="org.apache.log4j.DailyRollingFileAppender">  
        <param name="Append" value="true"/>  
        <param name="Encoding" value="UTF-8" />  
        <param name="File" value="/var/opt/meta/webapp/logs/meta_error.log"/>  
        <param name="DatePattern" value="'.'yyyyMMdd"/>  
        <layout class="org.apache.log4j.PatternLayout">  
            <param name="ConversionPattern" value="%d{yyyy/MM/dd HH:mm:ss} [%-5p] - %m%n"/>  
        </layout>  
        <filter class="org.apache.log4j.varia.LevelRangeFilter">  
            <param name="LevelMin" value="info"/>  
            <param name="LevelMax" value="error"/>  
            <param name="AcceptOnMatch" value="true"/>  
        </filter>  
    </appender>  
  
    <appender name="A_DEBUG" class="org.apache.log4j.DailyRollingFileAppender">  
        <param name="Append" value="true"/>  
        <param name="Encoding" value="UTF-8" />  
        <param name="File" value="/var/opt/meta/webapp/logs/meta_debug.log"/>  
        <param name="DatePattern" value="'.'yyyyMMdd"/>  
        <layout class="org.apache.log4j.PatternLayout">  
            <param name="ConversionPattern" value="%d{yyyy/MM/dd HH:mm:ss} [%-5p] - %m%n"/>  
        </layout>  
        <filter class="org.apache.log4j.varia.LevelRangeFilter">  
            <param name="LevelMin" value="debug"/>  
            <param name="LevelMax" value="error"/>  
            <param name="AcceptOnMatch" value="true"/>  
        </filter>  
    </appender>  
  
    <!-- framework logger -->  
    <logger name="java.sql">  
        <level value="warn" />  
    </logger>  
  
    <logger name="org.mybatis">  
        <level value="warn" />  
<!--        <appender-ref ref="STDOUT" />-->  
    </logger>  
  
    <logger name="org.apache">  
        <level value="warn" />  
    </logger>  
  
    <logger name="org.springframework">  
        <level value="warn" />  
    </logger>  
  
    <!-- the root logger -->  
    <root>  
        <level value="all" />  
        <appender-ref ref="A_ERROR" />  
        <appender-ref ref="A_DEBUG" />  
    </root>  
  
</log4j:configuration>

参考链接 :
【精选】日志框架(2) : Log4j介绍及使用_log4j日志的使用-CSDN博客

log4j配置详解 log4j中文文档_log4j官方文档-CSDN博客

本文作者:redtea 红茶的博客
本文链接:https://redtea.top版权声明:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可,非商业转载及引用请注明出处(作者、原文链接),商业转载请联系作者获得授权。

2023/05/12 posted in  开发技术