运行单元测试时禁用winston日志记录?
Posted
技术标签:
【中文标题】运行单元测试时禁用winston日志记录?【英文标题】:Disable winston logging when running unit tests? 【发布时间】:2016-11-16 17:26:37 【问题描述】:在执行节点模块的单元测试时,是否可以选择性地禁用 Winston 日志记录?
理想情况下,我希望在应用程序运行时进行日志记录以提供信息和调试目的,但在运行测试时不显示单元测试结果混乱。
我对 winston 的使用在我的模块内部,如下所示:
// MyModule.js
var logger = require('winston');
module.exports = function()
// does some stuff
// and logs some stuff like so:
logger.log('an informational message');
// MyModuleTest.js
describe('MyModule', fucntion()
it('should do some stuff', function()
var myModuleUnderTest = require('MyModule');
// some tests
【问题讨论】:
***.com/questions/22709882/… 【参考方案1】:我做的有点难看,但让我可以继续正常使用 Jest 的 --silent
选项。我只是将 Winston 的 silent
设置为 process.argv.indexOf("--silent") >= 0
。例如:
const logger = new winston.Logger(
…,
transports: [
new winston.transports.Console(
…,
silent: process.argv.indexOf("--silent") >= 0,
),
],
);
【讨论】:
silent: process.env.NODE_ENV === 'testing'
也是一个选项
是的。但是你不能直接使用 Jest 的 --silent
选项启用或禁用它,我觉得这很烦人。
啊,我应该说只有当你总是想在运行测试时让winston静音时才可以选择。
这在您测试一组测试文件时不起作用。看起来它不会使 argv 可供检查。【参考方案2】:
我们在测试中使用了silent
属性:
import logger from './my-defined-winston-logger'
//...
beforeAll(() =>
logger.silent = true;
)
afterAll(() =>
logger.silent = false;
)
【讨论】:
【参考方案3】:我意识到这已经很晚了,但我只是想用 jest 分享我的解决方案,因为我对这里找到的解决方案并不完全满意。我不能说我的解决方案非常优雅,并且可能只是隐藏了一些代码气味,因为我还在学习 TDD,但它确实有效。
在我的工作中,我经常想登录到通过winston.transports.File(filename: "<filename>")
传输指定的文件。假设我的日志文件是info.log
当然,在测试期间,我不想要
-
要写入此
info.log
的日志
info.log
不存在时创建。
这样做是为了避免副作用。上面的答案以及嘲笑足以避免 1. 但由于某种原因并没有避免 2. (解释原因如下)。
我设置项目的方式通常是这样的
src
├── app.js
├── services
│ ├── logging
│ │ ├── logger.js
│ │ └── logger_utils.js
│ ├── foo.js
│ ├── bar.js
│ └── etc.js
├── tests
│ ├── foo.test.js
│ ├── bar.test.js
│ └── etc.test.js
└── logs
└── info.log
主要关注与日志相关的文件。 logger.js
是我实例化并随后导出winston Logger 对象的地方。然后我在logger_utils.js
中编写辅助函数,以实现模块化和更轻松的测试。
当我的问题出现时,logger.js
包含在
problematic_logger.js
const winston = require("winston");
const path = require("path");
// define the log file directory
const log_dir = path.resolve(__dirname, "./../../logs/info.log");
// create logger
const logger = winston.createLogger(
transports: [
new winston.transports.File(
filename: log_dir
)
]
);
// export it
module.exports = logger;
然后我在logger_utils.js
中需要它,而这又在任何其他模块脚本中需要。所以,在测试中(除了测试logger_utils.js
),我只需要模拟logger_utils.js
中包含的函数,不用担心logger.js
,因为它只被logger_utils.js
调用。
现在,我对此并不完全确定,但我认为上面定义的 2. 尽管有模拟和静音,但仍然失败,因为 winston.createLogger()
仍在被调用,我相信即使在 - -silent 标志已设置。我不知道这是不是真的,但是上面的解决方案不起作用。
所以,(受this answer 启发)我决定做的只是在测试时不创建任何winston 对象。我通过将logger.js
文件更改为
fixed_logger.js
const winston = require("winston");
const path = require("path");
// define the log file directory
const log_dir = path.resolve(__dirname, "../../logs/info.log");
// if we are testing, don't create any winston object
if (process.env.NODE_ENV === "test")
// export
module.exports = ;
else
// behave normally otherwise
// create winston logger
const logger = winston.createLogger(
transports: [
new winston.transports.File(
filename: log_dir
)
]
);
// export it
module.exports = logger;
(NODE_ENV
在运行npm test
或npm run test:watch
等时自动设置为“测试”)
我们仍然需要导出一些东西让 logger_utils.js 在测试时不会中断,所以我们导出一个空对象。这很好,因为它会被嘲笑。
无论如何,这是我对 *** 的第一个回答。我希望这不会太灾难性,如果有人想了解更多细节,请告诉我。
【讨论】:
【参考方案4】:这是我的设置:
const createLogger, format, transports, config = require("winston");
let level, silent;
switch (process.env.NODE_ENV)
case "production":
level = "warning";
silent = false;
break;
case "test":
level = "emerg";
silent = true;
break;
default:
level = "debug";
silent = false;
break;
const options =
console:
level,
silent,
handleExceptions: true,
format: format.combine(
format.colorize(),
format.splat(),
format.printf(
info => `$new Date().toISOString() $info.level: $info.message`,
),
),
,
;
const logger = createLogger(
levels: config.syslog.levels,
transports: [new transports.Console(options.console)],
exitOnError: false,
);
module.exports = logger;
【讨论】:
silent
是我正在寻找的参数。【参考方案5】:
设置的东西对我不起作用,我使用的是winston v3.1.0,有一种创建记录器的新方法。
来自温斯顿网站:https://github.com/winstonjs/winston
推荐使用 winston 的方法是创建您自己的记录器。最简单的方法是使用 winston.createLogger:
const logger = winston.createLogger(
level: 'info',
format: winston.format.json(),
transports: [
//
// - Write to all logs with level `info` and below to `combined.log`
// - Write all logs error (and below) to `error.log`.
//
new winston.transports.File( filename: 'error.log', level: 'error' ),
new winston.transports.File( filename: 'combined.log' )
]
);
//
// If we're not in production then log to the `console` with the format:
// `$info.level: $info.message JSON.stringify( ...rest ) `
//
if (process.env.NODE_ENV !== 'production')
logger.add(new winston.transports.Console(
format: winston.format.simple()
));
所以我在 logger.js 中这样做
if (process.env.NODE_ENV === 'test')
return winston.createLogger(
transports: [ new winston.transports.Console( level: 'error') ]
);
这会停止所有日志消息,除非您有错误,我希望看到这有助于调试任何问题。
希望这会有所帮助。
【讨论】:
【参考方案6】:创建一个记录器:
const logger = createLogger(
level: "info",
format: format.json(),
transports: []
);
静默所有日志记录:
logger.transports.forEach((t) => (t.silent = true));
【讨论】:
【参考方案7】:Winston 传输有一个 silent
可以设置的属性,这可能比删除整个传输要好一些。
我为传输添加了一个名称,这样会更容易一些:
var logger = new winston.Logger();
logger.add(winston.transports.Console,
name: 'console.info',
colorize: true,
showLevel: true,
formatter: consoleFormatter,
)
然后在测试或设置中,我可以有选择地打开和关闭登录:
logger.transports['console.info'].silent = true // turns off
logger.transports['console.info'].silent = false // logging back on
【讨论】:
您可以将silent
添加到createLogger
,而不是添加到每个传输器:createLogger( silent: true, ... )
。如果您想静默所有日志,这很有用。【参考方案8】:
如果你使用的是 Jest,你可以像这样禁用它:
设置要在 jest 运行测试之前运行的设置文件。在package.json
:
"jest":
"setupFiles": ["<rootDir>/jest-set-up/index.js"]
在jest-set-up/index.js
:
import winston from 'winston'
winston.remove(winston.transports.Console)
【讨论】:
感谢@Meyer 的编辑,我尝试使用 4 个空格,但不确定我的文本没有被格式化为代码 你知道如何与ava实现相同的目标吗? 我正在使用 winston 日常传输,如何跳过要记录的测试用例 这太棒了!!,你也可以分享任何测试文件吗?以上是关于运行单元测试时禁用winston日志记录?的主要内容,如果未能解决你的问题,请参考以下文章