我对我的一个组件使用了jest快照测试,生成的快照文件很大(199Kb和4310行)。当快照测试失败时,所有快照文件都会打印到控制台(渲染时间为3-4秒),它给了我“你做错了”的感觉。
所以我的问题是:我是否正确使用快照测试?
组件代码:
import _ = require('lodash');
import React = require('react');
import {TranslatedMessage} from 'translator';
import {UserProfile} from './user-profile';
import {ICustomerProfile} from '../customer/customer-profile';
interface IUserProfile {
firstName: string;
lastName: string;
id: string;
customer: ICustomerProfile;
job: string;
email: string;
contacts: string;
phoneNumber: string;
}
interface IUserProfileProps {
contact: IUserProfile;
}
interface IUserProfileState {}
export class UserProfile extends React.Component<IUserProfileProps, IUserProfileState> {
constructor(props: IUserProfileProps) {
super(props);
}
public render(): JSX.Element {
return (
<div className="ext-admin-user-infos-details">
<div className="ext-admin-user-infos-details-content">
<div className="row">
<div className="col-md-12">
<h3>{this.props.contact.firstName } {this.props.contact.lastName}</h3>
<p className="ext-subtitle">
<span className="ext-minor">{this.props.contact.id}</span>
</p>
</div>
</div>
<div className="row">
<div className="col-md-8">
<div className="ext-admin-user-infos-card">
<h6>
<TranslatedMessage messageKey="common.labels.customer" />
</h6>
<ul>
<li>{this.props.contact.customer.name}</li>
</ul>
</div>
<div className="ext-admin-user-infos-card">
<h6>
<TranslatedMessage messageKey="admin.contact.infos.job" />
</h6>
<ul>
<li>{this.props.contact.job}</li>
</ul>
</div>
<div className="ext-admin-user-infos-card">
<h6>
<TranslatedMessage messageKey="admin.contact.infos.email" />
</h6>
<ul>
<li>{this.props.contact.email}</li>
</ul>
</div>
</div>
<div className="col-md-4">
<div className="ext-admin-user-infos-card">
<h6>
<TranslatedMessage messageKey="common.labels.followed" />
</h6>
<ol>
{this.renderContacts(this.props.contact.contacts)}
</ol>
</div>
<div className="ext-admin-user-infos-card">
<h6>
<TranslatedMessage messageKey="common.labels.phone" />
</h6>
<ul>
<li>{this.props.contact.phoneNumber}</li>
</ul>
</div>
</div>
</div>
</div>
</div>
);
}
protected renderContacts(contacts: IUserProfile[]): JSX.Element[] {
let contacts= [];
if (sales) {
_.map(sales, function(contact: IUserProfile): void {
salesContact.push(
<li>
{ contact.firstName}
{ contact.lastName}
</li>
);
});
}
return contacts;
}
}
和测试文件
jest.mock('TranslatedMessage');
import React = require('react');
import {render} from 'enzyme';
import {user} from '../../../tests/tools';
import {UserProfile} from '../../../app/components/user-profile/user-profile';
describe('UserProfile', () => {
it('should match the snapshot', () => {
const tree = render(<UserProfile user={user} />);
expect(tree).toMatchSnapshot();
});
});
答案 0 :(得分:1)
相信那种感觉。
您正确使用快照测试,但您已经达到了需要将大型组件分解为更小组件的程度。将它们分开将允许您模拟子组件,这将减少您的快照大小(每个快照,而不是聚合)并使您的差异更容易查看和修复。
例如,而不是:
export class UserProfile extends Component {
public render() {
return (
<div className="ext-admin-user-infos-details">
<div className="ext-admin-user-infos-details-content">
<div className="row">
<div className="col-md-12">
<h3>{this.props.contact.firstName } {this.props.contact.lastName}</h3>
<p className="ext-subtitle">
<span className="ext-minor">{this.props.contact.id}</span>
</p>
</div>
</div>
// ...
</div>
</div>
)
}
}
你这样做:
export class UserProfile extends Component {
public render() {
return (
<div className="ext-admin-user-infos-details">
<div className="ext-admin-user-infos-details-content">
<div className="row">
<div className="col-md-12">
<UserProfileName
first={this.props.contact.firstName}
last={this.props.contact.firstName}
contactId={this.props.contact.id}
/>
</div>
</div>
// ...
</div>
</div>
)
}
}
export class UserProfileName extends Component {
public render() {
return (
<div>
<h3>{this.props.contact.first} {this.props.contact.last}</h3>
<p className="ext-subtitle">
<span className="ext-minor">{this.props.contact.contactId}</span>
</p>
</div>
);
}
}
请注意,我已将用户名称的逻辑移至另一个组件。这是更新的测试,模拟子组件:
jest.mock('TranslatedMessage');
jest.mock('UserProfileName'); // Mock this and other children
import React = require('react');
import {render} from 'enzyme';
import {user} from '../../../tests/tools';
import {UserProfile} from '../../../app/components/user-profile/user-profile';
describe('UserProfile', () => {
it('should match the snapshot', () => {
const tree = render(<UserProfile user={user} />);
expect(tree).toMatchSnapshot();
});
});
此快照将比一个组件中的快照小得多。当然,您也可以对子组件进行测试:
import React = require('react');
import {render} from 'enzyme';
import {UserProfileName} from '../../../app/components/user-profile/user-profile-name';
describe('UserProfileName', () => {
it('should match the snapshot with all props', () => {
const tree = render(<UserProfile first="Test" last="Testerson" contactId="test-id" />);
expect(tree).toMatchSnapshot();
});
it('should render without a first name', () => {
const tree = render(<UserProfile last="Testerson" contactId="test-id" />);
expect(tree).toMatchSnapshot();
});
it('should render without a last name', () => {
const tree = render(<UserProfile first="Test" contactId="test-id" />);
expect(tree).toMatchSnapshot();
});
});
请注意,在这些测试中,我在最后添加了两个案例。当你像这样打破组件时,它更容易理解和测试子组件的特定用例!
最后,这种方法的另一个好处是,现在您有一个可重用的组件,它知道如何呈现用户名!您可以对此进行概括,并在需要时将其填入。
答案 1 :(得分:0)
您正在进行正确的测试,但是您应该将您的组件分成多个较小的组件,因为它目前太大了。
在使用enzyme
时,您might not want always to use render
for testing,因为它使输出变得如此之大。例如,在快照测试纯组件时,您应该使用shallow
。
我们正在使用react-test-rendered
for snapshot testing,它比酶更轻量。
答案 2 :(得分:-1)
如果您使用的是<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="Dating.js"></script>
</head>
<body>
<div id="startDate">Start Date:</div>
<div id="seconds">Seconds:</div>
<div id="interval">Interval:</div>
<div id="finalDate">Final Date:</div>
<div id="finalSeconds">Final Seconds:</div>
<div id="timeBetween">Seconds Between:</div>
<div id="reply">Reply:</div>
<div id="validated"></div>
</body>
</html>
,则应该使用浅渲染。
enzyme
您也可以使用import { shallow } from 'enzyme';
const component = shallow(<UserProfile user={user} />);
expect(component.text()).toMatchSnapshot();
:
react-test-renderer