当前位置: 首页 > 编程日记 > 正文

react测试组件_测试驱动的开发,功能和React组件

react测试组件

This article is part of my studies on how to build sustainable and consistent software. In this post, we will talk about the thinking behind the testing driven development and how to apply this knowledge to simple functions, web accessibility, and React components, mostly with Jest and React Testing Library.

本文是我关于如何构建可持续且一致的软件的研究的一部分。 在本文中,我们将讨论测试驱动开发背后的思想,以及如何将这些知识应用于简单功能,Web可访问性和React组件(主要是通过Jest和React Testing库)。

Automated tests are a big part of software development. It gives us, developers, confidence to ship code to be there, but we increase the confidence that the software will be up and running and working appropriately.

自动化测试是软件开发的重要组成部分。 它给我们开发人员提供了将代码发布到那里的信心,但是,我们增加了该软件可以正常运行并运行的信心。

I began my software career in the Ruby community writing tests from the first day I learned the language. The Ruby (and Rails) community was always strong in the testing automation area. It helped shape my mindset on how to write good software.

从学习语言的第一天起,我就在Ruby社区开始了我的软件职业生涯,编写测试。 Ruby(和Rails)社区在测试自动化领域一直很强大。 它帮助我塑造了如何编写优质软件的心态。

So using Ruby and Rails, I did a lot of backend stuff like background jobs, data structure modeling, API building, and so on. In this scope, the user is always one: the developer user. If building an API, the user would be the developer that's consuming the API. If building the models, the user would be the developer that will use this model.

因此,使用Ruby和Rails,我做了很多后端工作,例如后台作业,数据结构建模,API构建等等。 在此范围内,用户始终是一个:开发人员用户。 如果构建API,则用户将是使用该API的开发人员。 如果构建模型,则用户将是将使用此模型的开发人员。

Now doing a lof of frontend stuff too, after 1 intense year of building PWAs using mostly React and Redux, at first some thoughts came to my mind:

经过一年的紧张工作(主要使用React和Redux构建PWA)之后,现在也正在做一些前端工作,首先想到的是:

  • TDD is impossible when building UI stuff. How do I know if it is a div or span?

    在构建UI内容​​时,TDD是不可能的。 我怎么知道它是div还是span?
  • Testing can be "complex". Should I shallow or should I mount? Test everything? Ensure every div should be the right place?

    测试可以是“复杂的”。 我应该变浅还是应该安装? 测试一切? 确保每个div应该在正确的位置?

So I started re-thinking about these testing practices and how to make it productive.

因此,我开始重新考虑这些测试实践以及如何使其富有成效。

TDD is possible. If I'm wondering if I should expect a div or a span, I'm probably testing the wrong thing. Remember: tests should give us the confidence to ship, not necessarily to cover every bit or implementation details. We will dive into this topic later!

TDD是可能的。 如果我想知道是否应该使用div或span,我可能正在测试错误的东西。 请记住:测试应该使我们充满信心,而不一定要覆盖每一个细节或实施细节。 我们稍后将深入探讨该主题!

I want to build tests that:

我想建立以下测试:

  • Ensure the software works appropriately

    确保软件正常运行
  • Give the confidence to ship code to production

    放心将代码交付生产
  • Make us think about software design

    让我们考虑软件设计

And tests that make software:

以及制作软件的测试:

  • Easy to maintain

    易于维护
  • Easy to refactor

    易于重构

测试驱动开发 (Testing Driven Development)

TDD shouldn't be complex. It is just a process of 3 steps:

TDD应该不复杂。 这只是一个3个步骤的过程:

  • Make a test

    做个测试
  • Make it run

    使它运行
  • Make it right

    改正它

We start writing a simple test to cover how we expect the software works. Then we make the first implementation of the code (class, function, script, etc). Now the software is behaving. It works as expected. Time to make it right. Time to make it better.

我们开始编写一个简单的测试,以涵盖我们期望软件如何工作。 然后,我们对代码(类,函数,脚本等)进行第一个实现。 现在该软件运行正常。 它按预期工作。 是时候做对了。 是时候让它变得更好。

The goal is a clean code that works. We solve the "that works" problem first and then make the code clean.

目标是有效的干净代码。 我们首先解决“有效”的问题,然后使代码干净。

It is pretty simple. And it should be. I didn't say it is easy. But it is simple, straightforward, just 3 steps. Every time you exercise this process of writing tests first, code after, and then refactoring, you feel more confident.

这很简单。 它应该是。 我没有说这很容易。 但这很简单,直接,只需三个步骤。 每次执行此过程时,首先要编写测试,然后编写代码,然后进行重构,您会感到更加自信。

One good technique when writing your tests first is to think about use cases and simulate how it should be used (as a function, component, or used by a real user).

首先编写测试的一种好方法是考虑用例并模拟应如何使用它(作为功能,组件或由实际用户使用)。

功能 (Functions)

Let's apply this TDD thing into simple functions.

让我们将此TDD事物应用到简单函数中。

Some time ago I was implementing a draft feature for a real estate registration flow. Part of the feature was to show a modal if the user had a not finished real estate. The function we will implement is the one that answers if the user has at least one real estate draft.

不久前,我正在为房地产注册流程实施功能草案。 该功能的一部分是在用户未完成房地产交易时显示模式。 如果用户至少拥有一份房地产草案,我们将实现的功能就是回答这一功能。

So first step: writing the test! Let's think of the use cases of this function. It always responds a boolean: true or false.

所以第一步:编写测试! 让我们考虑一下此函数的用例。 它总是响应一个布尔值:true或false。

  • Has no unsaved real estate draft: false

    没有未保存的房地产汇票: false

  • Has at least one unsaved real estate draft: true

    至少有一份未保存的房地产汇票: true

Let's write the tests that represent this behavior:

让我们编写代表这种行为的测试:

describe('hasRealEstateDraft', () => {describe('with real estate drafts', () => {it('returns true', () => {const realEstateDrafts = [{address: 'São Paulo',status: 'UNSAVED'}];expect(hasRealEstateDraft(realEstateDrafts)).toBeTruthy();});});describe('with not drafts', () => {it('returns false', () => {expect(hasRealEstateDraft([])).toBeFalsy();});});
});

We wrote the tests. But when running it, it shows go red: 2 broken tests because we do not have the function implemented yet.

我们编写了测试。 但是运行它时,它会变成红色:2个失败的测试,因为我们尚未实现该功能。

Second step: make it run! In this case, it is pretty simple. We need to receive this array object and return if it has or hasn't at least one real estate draft.

第二步:使其运行! 在这种情况下,这非常简单。 我们需要接收此数组对象,并返回是否包含至少一个房地产草案。

const hasRealEstateDraft = (realEstateDrafts) => realEstateDrafts.length > 0;

Great! Simple function. Simple tests. We could go to step 3: make it right! But in this case, our function is really simple and we've already got it right.

大! 功能简单。 简单的测试。 我们可以进行第3步:正确设置! 但是在这种情况下,我们的功能确实很简单,并且我们已经做好了。

But now we need the function to get the real estate drafts and pass it to the hasRealEstateDraft.

但是现在我们需要函数来获取房地产草稿并将其传递给hasRealEstateDraft

Which use case we can think of?

我们能想到哪个用例?

  • An empty list of real estates

    空的房地产清单
  • Only saved real estates

    仅保存的房地产
  • Only unsaved real estates

    仅未保存的房地产
  • Mixed: save and unsaved real estates

    混合:保存和未保存的房地产

Let's write the tests to represent it:

让我们编写测试来表示它:

describe('getRealEstateDrafts', () => {describe('with an empty list', () => {it('returns an empty list', () => {const realEstates = [];expect(getRealEstateDrafts(realEstates)).toMatchObject([]);});});describe('with only unsaved real estates', () => {it('returns the drafts', () => {const realEstates = [{address: 'São Paulo',status: 'UNSAVED'},{address: 'Tokyo',status: 'UNSAVED'}];expect(getRealEstateDrafts(realEstates)).toMatchObject(realEstates);});});describe('with only saved real estates', () => {it('returns an empty list', () => {const realEstates = [{address: 'São Paulo',status: 'SAVED'},{address: 'Tokyo',status: 'SAVED'}];expect(getRealEstateDrafts(realEstates)).toMatchObject([]);});});describe('with saved and unsaved real estates', () => {it('returns the drafts', () => {const realEstates = [{address: 'São Paulo',status: 'SAVED'},{address: 'Tokyo',status: 'UNSAVED'}];expect(getRealEstateDrafts(realEstates)).toMatchObject([{address: 'Tokyo',status: 'UNSAVED'}]);});});
});

Great! We run the tests. It doesn't work.. yet! Now implement the function.

大! 我们运行测试。 它不起作用..呢! 现在实现该功能。

const getRealEstatesDrafts = (realEstates) => {const unsavedRealEstates = realEstates.filter((realEstate) => realEstate.status === 'UNSAVED');return unsavedRealEstates;
};

We simply filter by the real estate status and return it. Great, the tests are passing, the bar is green! And the software is behaving, but we can make it better: step 3!

我们仅按房地产状态进行过滤并返回。 太好了,测试通过了,酒吧是绿色的! 软件运行正常,但是我们可以做得更好:第3步!

What about extracting the anonymous function within the filter function and make the 'UNSAVED' be represented by an enum?

如何在filter函数中提取匿名函数并使'UNSAVED'由枚举表示呢?

const STATUS = {UNSAVED: 'UNSAVED',SAVED: 'SAVED',
};const byUnsaved = (realEstate) => realEstate.status === STATUS.UNSAVED;const getRealEstatesDrafts = (realEstates) => realEstates.filter(byUnsaved);

The tests are still passing and we have a better solution.

测试仍在通过,我们有一个更好的解决方案。

One thing to have in mind here: I isolated the data source from the logic. What does it mean? We get the data from local storage (data source), but we test only the functions responsible to the logic to get drafts and see if it has at least one draft. The functions with the logic, we ensure that it works and it is clean code.

这里要记住的一件事:我将数据源与逻辑隔离。 这是什么意思? 我们从本地存储(数据源)获取数据,但是我们仅测试负责获取草稿的逻辑的功能,并查看其是否至少有一份草稿。 具有逻辑的功能,我们确保它可以正常工作,并且代码干净。

If we get the localStorage inside our functions, it becomes hard to test. So we separate the responsibility and make the tests easy to write. Pure functions are easier to maintain and simpler to write tests.

如果我们将localStorage放入函数中,则很难进行测试。 因此,我们将职责分开,并使测试易于编写。 纯函数更易于维护,编写测试也更简单。

React组件 (React Components)

Now let's talk about React components. Back to the introduction, we talked about writing tests that test implementation details. And now we will see how we can make it better, more sustainable, and have more confidence.

现在让我们谈谈React组件。 回到引言,我们讨论了编写测试实现细节的测试。 现在,我们将看到如何使它变得更好,更具可持续性并更有信心。

A couple of days ago I was planning to build the new onboarding information for the real estate owner. It is basically a bunch of pages with the same design, but it changes the icon, title, and description of the pages.

几天前,我正计划为房地产所有者建立新的入职信息。 它基本上是一堆具有相同设计的页面,但是它更改了页面的图标,标题和描述。

I wanted to build just one component: Content and pass the information needed to render the correct icon, title, and description. I would pass businessContext and step as props and it would render the correct content to the onboarding page.

我只想构建一个组件: Content并传递渲染正确的图标,标题和描述所需的信息。 我将把businessContextstep作为道具传递,它将正确的内容呈现给入职页面。

We don't want to know if we will render a div or paragraph tag. Our test needs to ensure that for a given business context and step, the correct content will be there. So I came with these use cases:

我们不想知道是否将渲染div或段落标签。 我们的测试需要确保对于给定的业务环境和步骤,正确的内容在那里。 因此,我想到了这些用例:

  • The first step of the rental business context

    租赁业务环境的第一步
  • Last step of the rental business context

    租赁业务环境的最后一步
  • The first step of the sales business context

    销售业务环境的第一步
  • Last step of the sales business context

    销售业务环境的最后一步

Let's see the tests:

让我们看一下测试:

describe('Content', () => {describe('in the rental context', () => {const defaultProps = {businessContext: BUSINESS_CONTEXT.RENTAL};it('renders the title and description for the first step', () => {const step = 0;const { getByText } = render(<Content {...defaultProps} step={step} />);expect(getByText('the first step title')).toBeInTheDocument();expect(getByText('the first step description')).toBeInTheDocument();});it('renders the title and description for the forth step', () => {const step = 3;const { getByText } = render(<Content {...defaultProps} step={step} />);expect(getByText('the last step title')).toBeInTheDocument();expect(getByText('the last step description')).toBeInTheDocument();});});describe('in the sales context', () => {const defaultProps = {businessContext: BUSINESS_CONTEXT.SALE};it('renders the title and description for the first step', () => {const step = 0;const { getByText } = render(<Content {...defaultProps} step={step} />);expect(getByText('the first step title')).toBeInTheDocument();expect(getByText('the first step description')).toBeInTheDocument();});it('renders the title and description for the last step', () => {const step = 6;const { getByText } = render(<Content {...defaultProps} step={step} />);expect(getByText('the last step title')).toBeInTheDocument();expect(getByText('the last step description')).toBeInTheDocument();});});
});

We have one describe block for each business context and an it block for each step. I also created an accessibility test to ensure the component we are building is accessible.

对于每个业务上下文,我们都有一个describe块,对于每个步骤都有一个it块。 我还创建了可访问性测试,以确保我们正在构建的组件可访问。

it('has not accessibility violations', async () => {const props = {businessContext: BUSINESS_CONTEXT.SALE,step: 0,};const { container } = render(<Content {...props} />);const results = await axe(container);expect(results).toHaveNoViolations();
});

Now we need to make it run! Basically, the UI part of this component is just the icon, the title, and the description. Something like:

现在我们需要使其运行! 基本上,此组件的UI部分只是图标,标题和描述。 就像是:

<Fragment><Icon /><h1>{title}</h1><p>{description}</p>
</Fragment>

We just need to build the logic to get all these correct data. As I have the businessContext and the step in this component, I wanted to just do something like

我们只需要构建逻辑来获取所有这些正确的数据。 因为有了businessContext和该组件中的step ,所以我想做一些类似的事情

content[businessContext][step]

And it gets the correct content. So I built a data structure to work that way.

并且它获取正确的内容。 因此,我建立了一个数据结构以这种方式工作。

const onboardingStepsContent = {alugar: {0: {Icon: Home,title: 'first step title',description: 'first step description',},// ...},vender: {0: {Icon: Home,title: 'first step title',description: 'first step description',},// ...},
};

It's just an object with the first keys as the business context data and for each business context, it has keys that represent each step of the onboarding. And our component would be:

它只是一个具有第一个键作为业务上下文数据的对象,并且对于每个业务上下文,它都有代表入门过程中每个步骤的键。 我们的组件将是:

const Content = ({ businessContext, step }) => {const onboardingStepsContent = {alugar: {0: {Icon: Home,title: 'first step title',description: 'first step description',},// ...},vender: {0: {Icon: Home,title: 'first step title',description: 'first step description',},// ...},};const { Icon, title, description } = onboardingStepsContent[businessContext][step];return (<Fragment><Icon /><h1>{title}</h1><p>{description}</p></Fragment>);
};

It works! Now let's make it better. I wanted to make the get content more resilient. What if it receives a step that doesn't exist for example? These are the use cases:

有用! 现在,让它变得更好。 我想使获取的内容更具弹性。 例如,如果收到不存在的步骤怎么办? 这些是用例:

  • The first step of the rental business context

    租赁业务环境的第一步
  • Last step of the rental business context

    租赁业务环境的最后一步
  • The first step of the sales business context

    销售业务环境的第一步
  • Last step of the sales business context

    销售业务环境的最后一步
  • Inexistent step of the rental business context

    租赁业务环境中不存在的步骤
  • Inexistent step of the sales business context

    销售业务环境中不存在的步骤

Let's see the tests:

让我们看一下测试:

describe('getOnboardingStepContent', () => {describe('when it receives existent businessContext and step', () => {it('returns the correct content for the step in "alugar" businessContext', () => {const businessContext = 'alugar';const step = 0;expect(getOnboardingStepContent({ businessContext, step })).toMatchObject({Icon: Home,title: 'first step title',description: 'first step description',});});it('returns the correct content for the step in "vender" businessContext', () => {const businessContext = 'vender';const step = 5;expect(getOnboardingStepContent({ businessContext, step })).toMatchObject({Icon: ContractSign,title: 'last step title',description: 'last step description',});});});describe('when it receives inexistent step for a given businessContext', () => {it('returns the first step of "alugar" businessContext', () => {const businessContext = 'alugar';const step = 7;expect(getOnboardingStepContent({ businessContext, step })).toMatchObject({Icon: Home,title: 'first step title',description: 'first step description',});});it('returns the first step of "vender" businessContext', () => {const businessContext = 'vender';const step = 10;expect(getOnboardingStepContent({ businessContext, step })).toMatchObject({Icon: Home,title: 'first step title',description: 'first step description',});});});
});

Great! Now let's build our getOnboardingStepContent function to handle this logic.

大! 现在,让我们构建getOnboardingStepContent函数来处理此逻辑。

const getOnboardingStepContent = ({ businessContext, step }) => {const content = onboardingStepsContent[businessContext][step];return content? content: onboardingStepsContent[businessContext][0];
};

We try to get content. If we have it, just return it. If we don't have it, return the first step of the onboarding.

我们尝试获取内容。 如果有,请退回。 如果没有,请返回入职的第一步。

Neat! But we can improve it. What about using the || operator? No need to assign to a variable, no need to use a ternary.

整齐! 但是我们可以改善它。 怎样使用|| 操作员? 无需分配变量,无需使用三进制。

const getOnboardingStepContent = ({ businessContext, step }) =>onboardingStepsContent[businessContext][step] ||onboardingStepsContent[businessContext][0];

If it finds the content, just return it. If it didn't find, return the first step of the given business context.

如果找到内容,则将其返回。 如果找不到,请返回给定业务环境的第一步。

Now our component is only UI.

现在,我们的组件只是UI。

const Content = ({ businessContext, step }) => {const {Icon,title,description,} = getOnboardingStepContent({ businessContext, step });return (<Fragment><Icon /><h1>{title}</h1><p>{description}</p></Fragment>);
};


最后的想法 (Final thoughts)

I like to think deeply about the tests I'm writing. And I think all developers should too. It does need to give us the confidence to ship more code and have a bigger impact on the market we are working on.

我喜欢对正在编写的测试进行深入思考。 而且我认为所有开发人员也应该这样做。 它确实需要使我们有信心发布更多代码,并对我们正在开发的市场产生更大的影响。

Like all code, when we write smelly and bad tests, it influences other developers to follow the "pattern". It gets worse in bigger companies. It scales badly. But we are always able to stop, reflect on the status quo, and take action to make it better.

像所有代码一样,当我们编写有臭味和不良的测试时,它会影响其他开发人员遵循“模式”。 在大公司中情况变得更糟。 它缩放严重。 但是我们总是能够停下来,反思现状,并采取行动使其变得更好。

I shared some resources I found interesting reading and learning. If you want to get a great introduction to TDD, I really recommend TDD by example, a book from Kent Beck.

我分享了一些有趣的阅读和学习资源。 如果您想对TDD进行很好的介绍,我真的以示例的方式推荐了TDD,这是一本肯特·贝克(Kent Beck)的书。

I will write more about tests, TDD, and React. And how we can make our software more consistent and feel safe when shipping code to production.

我将写更多关于测试,TDD和React的内容。 以及在将代码发布到生产环境时,如何使我们的软件更一致,更安全。

依存关系 (Dependencies)

  • jest-axe: jest matchers for testing accessibility

    jest-axe :用于测试可访问性的jest匹配器

  • testing-library/react-testing-library: testing utilities to help test react

    testing-library / react-testing-library :测试实用程序以帮助测试React

  • testing-library/jest-dom: jest matchers to test the state of the DOM

    testing-library / jest-dom :用于测试DOM状态的玩笑匹配者

资源资源 (Resources)

  • Beginner JavaScript Course

    初学者JavaScript课程

  • React for Beginners Course

    对初学者的React课程

  • Advanced React Course

    高级React课程

  • ES6 Course

    ES6课程

  • The Road to learn React

    学习React之路

  • JavaScript Fundamentals Before Learning React

    学习React之前JavaScript基础

  • Reintroducing React: V16 and Beyond

    重新引入React:V16及更高版本

  • Advanced React Patterns With Hooks

    带钩的高级React模式

  • Practical Redux

    实用的Redux

  • JavaScript Course by OneMonth

    OneMonthJavaScript课程

  • Test Driven Development by example book by Kent Beck

    肯特·贝克(Kent Beck)的示例书进行测试驱动开发

  • Testable Javascript book by Mark Ethan Trostler

    Mark Ethan Trostler编写的可测试的Java脚本书

  • Blog post source code

    博客文章源代码

  • Testing React applications with jest, jest-axe, and react-testing-library

    用玩笑,玩笑轴和React-Testing-Library测试React应用程序

  • Modern React testing, part 3: Jest and React Testing Library

    现代React测试,第3部分:Jest和React测试库

  • What we found when we tested tools on the world’s least-accessible webpage

    在世界上访问最少的网页上测试工具时发现的东西

  • Testing Implementation Details

    测试实施细节

  • Learn React by building an App

    通过构建应用来学习React

You can other articles like this on my blog.

您可以像这样的其他文章 在我的博客上 。

翻译自: https://www.freecodecamp.org/news/tdd-functions-and-react-components/

react测试组件

相关文章:

CDOJ 1073 线段树 单点更新+区间查询 水题

H - 秋实大哥与线段树Time Limit:1000MS Memory Limit:65535KB 64bit IO Format:%lld & %llu Submit Status Practice UESTC 1073Appoint description: System Crawler (2016-04-24)Description “学习本无底&#xff0c;前进莫徬徨。” 秋实大哥对一旁玩手机的学…

1小时学会:最简单的iOS直播推流(五)yuv、pcm数据的介绍和获取

最简单的iOS 推流代码&#xff0c;视频捕获&#xff0c;软编码(faac&#xff0c;x264)&#xff0c;硬编码&#xff08;aac&#xff0c;h264&#xff09;&#xff0c;美颜&#xff0c;flv编码&#xff0c;rtmp协议&#xff0c;陆续更新代码解析&#xff0c;你想学的知识这里都有…

beta冲刺第一天

1、今天解决的进度 成员进度陈家权回复界面设计&#xff0c;由于成员变动加上和其他成员距离较远&#xff0c;服务器404赖晓连改进Alpha版本页面没能及时更新的问题雷晶获取提问问题时间更新到数据库林巧娜今天的任务是夜间模式功能块&#xff0c;没有完成&#xff0c;查找了很…

angular绑定数据_Angular中的数据绑定说明

angular绑定数据数据绑定 (Data Binding) 动机 (Motivation) Data often defines the look of an application. Interpreting that data into the user interface involves class logic (.component.html) and a template view (.component.ts) . Angular connects them throug…

WPF判断两个时间大小避免误差

进行查询操作的时候&#xff0c;经常用到判断开始时间和结束时间大小的条件&#xff0c;由于从控件上获取的时间除了年月日时分秒&#xff0c;还包括毫秒、微秒等&#xff0c;导致直接判断时间大小的时候会产生一些误差&#xff0c;如下&#xff1a; 结果分析&#xff1a;年月日…

1小时学会:最简单的iOS直播推流(六)h264、aac、flv介绍

最简单的iOS 推流代码&#xff0c;视频捕获&#xff0c;软编码(faac&#xff0c;x264)&#xff0c;硬编码&#xff08;aac&#xff0c;h264&#xff09;&#xff0c;美颜&#xff0c;flv编码&#xff0c;rtmp协议&#xff0c;陆续更新代码解析&#xff0c;你想学的知识这里都有…

分享一款Markdown的css样式

使用 本样式在这个样式的基础上做了一些修改&#xff0c; 主要是对于表格和代码块以及一些细节的修改。 主要目的是用在chrome的扩展 Markdown Preview Plus中&#xff0c; 替换其内置的样式。 由于 Markdown Preview Plus对css文件大大小有要求&#xff08;小于8K&#xff09;…

远程桌面怎么持续连接_如何拥有成功且可持续的远程产品管理职业

远程桌面怎么持续连接Remote work is rapidly growing in all industries. Some professionals might try to push away this new way of working, seeing it as simply a current necessity. They might not think its fit for a product manager who’s constantly managing …

1小时学会:最简单的iOS直播推流(七)h264/aac 硬编码

最简单的iOS 推流代码&#xff0c;视频捕获&#xff0c;软编码(faac&#xff0c;x264)&#xff0c;硬编码&#xff08;aac&#xff0c;h264&#xff09;&#xff0c;美颜&#xff0c;flv编码&#xff0c;rtmp协议&#xff0c;陆续更新代码解析&#xff0c;你想学的知识这里都有…

Linux日常命令记录

1、查找进程 ps -ef | grep javajps 2、杀死进程 kill -9 1827 3、进入tomcat中的日志文件夹 cd logs 4、查看日志 tail -f catalina.outtail -n 10000 catalina.out 5、查看tomcat的连接数 ss -nat|grep -i "8081"|wc -lnetstat -nat | grep -i "8081" | …

【特效】移入显示移出隐藏

移入显示移出隐藏的效果也是很常见的&#xff0c;例如&#xff1a; 如果页面有有多处地方有此效果&#xff0c;那么也可以合并到一块&#xff0c;只写一段js代码&#xff0c;只要注意控制样式和class名字和用于js获取元素的class名字分开设置就可以了。代码很简单&#xff0c;用…

web前端开发最佳实践_学习前端Web开发的最佳方法

web前端开发最佳实践为什么要进行网站开发&#xff1f; (Why web development?) Web development is a field that is not going anywhere anytime soon. The web is moving quickly, and there are regular improvements to the devices many people use daily. Web开发是一个…

使用C#的HttpWebRequest模拟登陆网站

很久没有写新的东西了&#xff0c;今天在工作中遇到的一个问题&#xff0c;感觉很有用&#xff0c;有种想记下来的冲动。 这篇文章是有关模拟登录网站方面的。 实现步骤&#xff1b; 启用一个web会话发送模拟数据请求&#xff08;POST或者GET&#xff09;获取会话的CooKie 并根…

1小时学会:最简单的iOS直播推流(番外)运行不起AWLive的demo的同学请看这里

最简单的iOS 推流代码&#xff0c;视频捕获&#xff0c;软编码(faac&#xff0c;x264)&#xff0c;硬编码&#xff08;aac&#xff0c;h264&#xff09;&#xff0c;美颜&#xff0c;flv编码&#xff0c;rtmp协议&#xff0c;陆续更新代码解析&#xff0c;你想学的知识这里都有…

学习css布局

非常经典 http://zh.learnlayout.com/ float和position:absolute都是inline-block&#xff0c;破坏性的。absolute根据父元素定位&#xff08;static父元素除外&#xff09;。div也将不再是一行的块了。 position:relative自身定位。top&#xff0c;left是根据自己原本位置&…

csv文件示例_如何在R中使用数据框和CSV文件-带有示例的详细介绍

csv文件示例Welcome! If you want to start diving into data science and statistics, then data frames, CSV files, and R will be essential tools for you. Lets see how you can use their amazing capabilities.欢迎&#xff01; 如果您想开始研究数据科学和统计学&…

1小时学会:最简单的iOS直播推流(八)h264/aac 软编码

最简单的iOS 推流代码&#xff0c;视频捕获&#xff0c;软编码(faac&#xff0c;x264)&#xff0c;硬编码&#xff08;aac&#xff0c;h264&#xff09;&#xff0c;美颜&#xff0c;flv编码&#xff0c;rtmp协议&#xff0c;陆续更新代码解析&#xff0c;你想学的知识这里都有…

003小插曲之变量和字符串

变量&#xff1a;赋值&#xff08;名字值&#xff09;&#xff1b;变量名&#xff1a;字母分大小写/数字/下划线&#xff0c;不能以数字开头&#xff1b;拼接&#xff1b;原始字符串r&#xff1b; 专业优秀的名称&#xff1a;teacher/num/name/test/temp >>> teacher小…

mysql插入大量数据

创建实验表&#xff1a; CREATE TABLE a ( id int(11) NOT NULL AUTO_INCREMENT, name char(50) NOT NULL, type char(20) NOT NULL, PRIMARY KEY (id)) ENGINEInnoDB&#xff1b; 创建存储语句&#xff1a; delimiter // create procedure insertdata() begin declare i int …

十六进制190的2进制数_十六进制数系统解释

十六进制190的2进制数Hexadecimal numbers, often shortened to “hex numbers” or “hex”, are numbers represented in base 16 as opposed to base 10 that we use for everyday arithmetic and counting.十六进制数字(通常缩写为“十六进制数字”或“十六进制”)是以16为…

初学ssm框架的信息

ssm框架&#xff0c;就是Spring ,SpringMVC ,mybstis 的简称&#xff0c;我们是从mybstis 开始学起的&#xff0c;mybatis的作用作为一个连接数据库的框架&#xff0c;可以很好配置连接好数据库&#xff0c; 有mybatis,我们对数据库增删改查的操作更为简便了。SSM框架&#xff…

转:YUV RGB 常见视频格式解析

转&#xff1a; http://www.cnblogs.com/qinjunni/archive/2012/02/23/2364446.html YUV RGB 常见视频格式解析 I420是YUV格式的一种&#xff0c;而YUV有packed format和planar format两种&#xff0c;而I420属于planar format的一种。  同时I420表示了YUV的采样比例4:2:0。4…

1小时学会:最简单的iOS直播推流(十)librtmp使用介绍

最简单的iOS 推流代码&#xff0c;视频捕获&#xff0c;软编码(faac&#xff0c;x264)&#xff0c;硬编码&#xff08;aac&#xff0c;h264&#xff09;&#xff0c;美颜&#xff0c;flv编码&#xff0c;rtmp协议&#xff0c;陆续更新代码解析&#xff0c;你想学的知识这里都有…

导入语句 python_Python导入语句说明

导入语句 pythonWhile learning programming and reading some resources you’d have come across this word ‘abstraction’ which simply means to reduce and reuse the code as much as possible.在学习编程和阅读一些资源时&#xff0c;您会遇到“抽象”一词&#xff0c…

网页性能测试---webpagetest

http://www.webpagetest.org/转载于:https://www.cnblogs.com/cai-yu-candice/p/8194866.html

1小时学会:最简单的iOS直播推流(十一)spspps和AudioSpecificConfig介绍(完结)

最简单的iOS 推流代码&#xff0c;视频捕获&#xff0c;软编码(faac&#xff0c;x264)&#xff0c;硬编码&#xff08;aac&#xff0c;h264&#xff09;&#xff0c;美颜&#xff0c;flv编码&#xff0c;rtmp协议&#xff0c;陆续更新代码解析&#xff0c;你想学的知识这里都有…

ES5 数组方法forEach

ES6已经到了非学不可的地步了&#xff0c;对于ES5都不太熟的我决定是时候学习ES5了。 1. js 数组循环遍历。 数组循环变量&#xff0c;最先想到的就是 for(var i0;i<count;i)这样的方式了。 除此之外&#xff0c;也可以使用较简便的forEach 方式 2. forEach 函数。 使用如…

pytorch深度学习_了解如何使用PyTorch进行深度学习

pytorch深度学习PyTorch is an open source machine learning library for Python that facilitates building deep learning projects. Weve published a 10-hour course that will take you from being complete beginner in PyTorch to using it to code your own GANs (gen…

LwIP Application Developers Manual12---Configuring lwIP

1.前言 2.LwIP makefiles With minimal featuresC_SOURCES \ src/api/err.c \ src/core/init.c \ src/core/mem.c \ src/core/memp.c \ src/core/netif.c \ src/core/pbuf.c \ src/core/stats.c \ src/core/udp.c \ src/core/ipv4/icmp.c \ src/core/ipv4/inet.c \ src/core/i…

仿斗鱼聊天:基于CoreText的面向对象图文排版工具AWRichText

AWRichText 基于CoreText&#xff0c;面向对象&#xff0c;极简&#xff0c;易用&#xff0c;高效&#xff0c;支持精确点击&#xff0c;UIView混排&#xff0c;GIF动图&#xff0c;并不仅仅局限于图文混排的富文本排版神器。 代码地址&#xff1a;https://github.com/hardman/…