单元测试基础知识(三)

9.单测工具简介

JUnit

Java用的最多的单测框架,使用非常简单,主流IDE基本都集成了JUnit,具体用法就不介绍了,可以花十分钟看看官方文档http://junit.org/junit4/

TestNg

是一款基于junit框架上的加强版单元测试框架,具备更多更强大的功能,能够执行比较复杂的程序代码,具体用法这里也不介绍了,可以花十分钟看看官方文档http://testng.org/doc/documentation-main.html

Runner

JUnit的Runner是指继承了org.junit.runner.Runner的类,是用来真正执行单测方法的类,JUnit有提供默认的Runner,如org.junit.runners.JUnit4,也可以通过@RunWith注解来指定自定义的Runner,如@RunWith(SpringRunner.class)

Runner的介绍可以参考这篇文章: 
http://www.mscharhag.com/java/understanding-junits-runner-architecture

通过自定义Runner,可以简化单测的开发,例如,在Spring没有提供Runner时,为Spring应用编写单测,需要自己初始化Spring上下文,然后从上下文中获取要测试的Bean,使用起来比较麻烦。

对于自定义Runner来说,一般会继承JUnit的org.junit.runners.BlockJUnit4ClassRunner,BlockJUnit4ClassRunner主要提供了下面的功能:

  • 反射创建单测类实例
  • 找出单测方法(被@Test注解的方法)
  • 其它JUnit注解支持,如@After、@Before等等
  • 反射执行单测方法

SpringRunner通过继承BlockJUnit4ClassRunner,在其基础上提供了自动初始化Spring上下文,单测类中的@Resource等注解的处理,等等一系列方便编写Spring单测的功能。

如果我们想实现在单测方法前后执行一些逻辑,我们除了可以使用@Before注解,还可以通过实现自定Runner来实现:

1.  import org.junit.runners.BlockJUnit4ClassRunner;
2.  import org.junit.runners.model.FrameworkMethod;
3.  import org.junit.runners.model.InitializationError;
4.  import org.junit.runners.model.Statement;
5.   
6.  public class TestRunner extends BlockJUnit4ClassRunner {
7.   
8.      public TestRunner(Class<?> klass) throws InitializationError {
9.          super(klass);
10.                }
11.             
12.                @Override
13.                protected Statement methodBlock(FrameworkMethod method) {
14.                    //FrameworkMethod 是单测方法的包装类
15.             
16.                    //获取父类处理的结果,以便使用JUnit提供的注解的功能
17.                    Statement block = super.methodBlock(method);
18.             
19.                    //自定义的逻辑
20.                    Statement newBlock = new Statement() {
21.                        @Override
22.                        public void evaluate() throws Throwable {
23.                            //这里可以在单测方法执行前做一些自定义逻辑
24.                            System.out.println("TestRunner before : " + method.getName());
25.             
26.                            block.evaluate();//单测方法执行,包含@Before等注解处理逻辑
27.             
28.                            //这里可以在单测方法执行后做一些自定义逻辑
29.                            System.out.println("TestRunner after : " + method.getName());
30.                        }
31.                    };
32.             
33.                    return newBlock;
34.                }
35.             
36.            }
37.             
38.            import org.junit.Test;
39.            import org.junit.runner.RunWith;
40.             
41.            @RunWith(TestRunner.class)
42.            public class BTestClass {
43.             
44.                @Test
45.                public void test(){
46.                    System.out.println("test b");
47.                }
48.             
49.            }
50.             
51.            //运行输出
52.            //TestRunner before : test
53.            //test b
54.            //TestRunner after : test
 
在JUnit内部,其实就是用类似的方式来实现@Before、@After等等注解功能的,通过层层的包装Statement类,来实现功能的扩展。

Rule

Rule是JUnit4.7新增加的功能,是JUnit的另一种扩展机制,可以扩展单测方法的执行。上面TestRunner的功能也可以通过Rule机制来实现:

1.  import org.junit.rules.TestRule;
2.  import org.junit.runner.Description;
3.  import org.junit.runners.model.Statement;
4.   
5.  public class EchoRule implements TestRule {
6.   
7.      @Override
8.      public Statement apply(Statement base, Description description) {
9.          Statement newBlock = new Statement() {
10.                        @Override
11.                        public void evaluate() throws Throwable {
12.                            //这里可以在单测方法执行前做一些自定义逻辑
13.                            System.out.println("EchoRule before : " + description.getMethodName());
14.             
15.                            base.evaluate();//单测方法执行,包含@Before等注解处理逻辑
16.             
17.                            //这里可以在单测方法执行后做一些自定义逻辑
18.                            System.out.println("EchoRule after : " + description.getMethodName());
19.                        }
20.                    };
21.                    return newBlock;
22.                }
23.             
24.            }
25.            import org.junit.Rule;
26.            import org.junit.Test;
27.             
28.            public class BTestClass {
29.             
30.                @Rule
31.                public EchoRule rule = new EchoRule();//必需要是public
32.             
33.                @Test
34.                public void test() {
35.                    System.out.println("test b");
36.                }
37.             
38.            }
39.             
40.            //输出
41.            //EchoRule before : test
42.            //test b
43.            //EchoRule after : test

可以看到Rule更多的是对单测方法执行前后的一些逻辑的扩展,@Rule注解的属性必需是public的实例属性,如果想在所有单测方法执行前后进行处理(类似@BeforeClass、@AfterClass逻辑),可以通过@ClassRule注解来做到,被@ClassRule的属性必需是static public的属性

Rule机制相对Runner的好处在于,Runner只能指定一个,而一个单测类可以指定多个Rule,Spring也有Rule的实现,在即想使用其它框架的Runner又想使用Spring的单测扩展时,可以使用其它框架的Runner,然后使用Spring的Rule,来组合使用,如:

1.  import org.junit.ClassRule;
2.  import org.junit.Rule;
3.  import org.junit.Test;
4.  import org.junit.runner.RunWith;
5.  import org.mockito.runners.MockitoJUnitRunner;
6.  import org.springframework.test.context.junit4.rules.SpringClassRule;
7.  import org.springframework.test.context.junit4.rules.SpringMethodRule;
8.   
9.  @RunWith(MockitoJUnitRunner.class)
10.            @ContextConfiguration(locations="classpath:spring-root.xml")
11.            public class BTestClass {
12.             
13.                @ClassRule
14.                public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
15.             
16.                @Rule
17.                public final SpringMethodRule springMethodRule = new SpringMethodRule();
18.             
19.                @Test
20.                public void test() {
21.                    System.out.println("test b");
22.                }
23.             
24.            }

JUnit自带了一些方便使用的Rule实现,可以参考下面的文档 
https://github.com/junit-team/junit4/wiki/Rules

Mock框架

在真实项目中,往往需要依赖很多外部的接口,如HSF等接口,而我们在运行单测的时候RPC接口可能还未开发完成或者因为环境问题,无法访问,这时我们想要测试自己部分的逻辑,就需要使用到Mock框架,来屏蔽掉外部系统的影响。

使用Mock通常会带来以下一些好处:

  • 隔绝其他模块出错引起本模块的测试错误
  • 隔绝其他模块的开发状态,只要定义好接口,不用管他们开发有没有完成
  • 一些速度较慢的操作,可以用Mock Object代替,使单测快速返回
  • 隔离环境对单测执行的影响,实现在没有外部服务时也能运行单测

常见的Mock框架有EasyMock、Mocktio、JMockit、PowerMock等,个人只简单用过Mocktio和JMockit,就功能上,JMockit的功能更强,能Mock静态方法等,但是根据之前的使用来看,比较难以驾驭,因为JMockit使用的是Java5的Instrumentation机制,会在运行时修改字节码,导致碰到问题时比较难以调试,相对的网络资料也比较少,而Mocktio的使用比较简单明了,因此推荐使用Mocktio

关于Mocktio的使用可以参考文档: 
[https://static.javadoc.io/org.mockito/mockito-core/2.7.22/org/mockito/Mockito.html 
https://juejin.im/entry/578f11aec4c971005e0caf82](https://static.javadoc.io/org.mockito/mockito-core/2.7.22/org/mockito/Mockito.html 
https://juejin.im/entry/578f11aec4c971005e0caf82)

因为Mocktio是使用Cglib来创建代理的,所以对于被Mock的对象来说,要求和Cglib创建代理的要求一样,如不能是final类、不能代理private方法等等限制。

有时候可能需要mock void方法,可以使用下面的方式

1.  OssCache cache = Mockito.mock(OssCache.class);
2.   
3.  Mockito.doNothing().when(cache).putToKey("key", "val");
4.  Mockito.doThrow(new RuntimeException("exp")).when(cache).deleteObj("key");
5.   
6.  cache.putToKey("key", "val");
7.  try {
8.      cache.deleteObj("key");
9.      fail("mast throw exception");
10.            } catch (RuntimeException e) {
11.                assertTrue("exp".equals(e.getMessage()));
12.            }
13.             
14.            Mockito.verify(cache).putToKey("key", "val");
15.            Mockito.verify(cache).deleteObj("key");

当Mockito的注解使用起来比较方便,具体注解的使用参见前面链接的文档,Mockito处理注解是通过MockitoAnnotations.initMocks(target)来处理的,而Mockito提供的Runner和Rule其实就是简单的在单测方法执行前执行该行代码,所以可以通过@RunWith(MockitoJUnitRunner.class)或@Rule public MockitoRule mockitoRule = MockitoJUnit.rule()方式来使用Mockito注解功能,当和Spring Test一起使用时,因为一般会使用Spring的Runner,所以可以通过Rule的方式来使用Mockito的注解功能

关于Mockito的大概原理如下

主要通过ThreadLocal将我们要mock的方法和对应的返回值关联起来

内存数据库

在项目中经常会使用到Mysql等数据库,但是在单测运行时,如果访问Mysql等外部服务器,会造成:

  • 单测运行慢
  • 单测运行依赖环境,在无法访问Mysql时,单测无法运行
  • 单测可能会运行的非常频繁,造成Mysql中非常多的垃圾数据
  • 单测依赖数据库中某些特定的数据,造成换个Mysql数据库时单测运行失败

那么如何解决上面的问题,一种方式是Mock掉所有DAO的类,这种方式需要写非常多的Mock,单测写起来比较麻烦,且DAO层面问题无法测试到;另一种方式就是使用内存数据库,内存数据库兼容SQL,启动速度快,数据存放在内存中单测运行后自动丢弃,非常适合单测时使用

常见的内存数据库有很多,但是鉴于单测场景,考虑到安装方便(直接Maven依赖),了解到的有HSQL、H2、Derby等,H2的官网上有个对比表http://www.h2database.com/html/main.html

考虑到目前我们使用的是Mysql数据库,而H2有Mysql模式,对Mysql的语法支持的最好,所以建议使用H2数据库来作为单测数据库,但是H2并不支持所有的Mysql语法,还是有不少的Mysql语法或函数并不支持,对于建表语句而言,可以使用语法转换工具https://github.com/bgranvea/mysql2h2-converter

Spring对嵌入式数据库支持的非常好,可以通过下面的配置来创建嵌入式数据库数据源,同时可以指定初始化表和数据库的脚本

1.  <jdbc:embedded-database id="dataSource" generate-name="true" type="H2">
2.      <jdbc:script location="classpath:/sql/test_schema.sql" />
3.      <jdbc:script location="classpath:/sql/test_init_data.sql" />
4.  </jdbc:embedded-database>

具体使用可以参考Spring的文档https://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html#jdbc-embedded-database-support

除了H2,还可以使用MariaDB4j,MariaDB的Java包装版本(用Java代码安装MariaDB精简版然后启动,比较重) 
https://github.com/vorburger/MariaDB4j

Spring Test介绍

当应用使用了Spring时,编写单测时需要每次手动的初始化Spring上下文,这种方式不仅繁琐,而且不能复用Spring上下文,导致单测执行时间变长,为此,Spring提供了对单测的支持,也就是Spring Test模块

Spring和JUnit的整合,提供了对应的Runner和Rule,我们平常使用的比较多的是Spring的Runner,即SpringJUnit4ClassRunner或者SpringRunner(Spring4.3),Spring的Runner会根据配置自动初始化Spring上下文,并在单测方法执行时对其进行依赖注入,避免手动的getBean操作,简单使用如下

1.  @RunWith(SpringJUnit4ClassRunner.class)
2.  @ContextConfiguration("classpath:spring-test-main.xml")
3.  public class Test {
4.   
5.      @Resource
6.      private SomeBean bean;
7.   
8.      @Test
9.      public void test(){
10.                    String someVal = bean.someMethod();
11.                }
12.             
13.            }

Spring Test提供@ContextConfiguration来让我们指定要初始Spring上下文的配置,支持Spring的各种配置方式,如XML、JavaConfig等等方式,@ContextConfiguration和@RunWith等注解都可以注解在基类上,所以可以提供一个基础类来简化单测的编写

1.  @RunWith(SpringJUnit4ClassRunner.class)
2.  @ContextConfiguration("classpath:base-context.xml")
3.  public class XXXTestBase {
4.   
5.  }
6.   
7.  @ContextConfiguration("classpath:extended-context.xml")
8.  public class YYYTest extends XXXTestBase{
9.   
10.            }

默认情况下,子类可以继承父类的@ContextConfiguration配置,同时可以追加自己的配置,当程序非常模块化时,可以通过指定特定的配置文件来减少初始化Bean的数量,以便提高单测的执行速度

@TestExecutionListeners注解是Spring Test用来注册TestExecutionListener的注解,提供的类似于JUnit的Before、After的扩展方法,父类的@TestExecutionListeners注解配置通样可以被子类继承,子类也可以提供自己个性的@TestExecutionListeners配置

1.  //可以通过@Order指定TestExecutionListener的顺序
2.  public interface TestExecutionListener {
3.      void beforeTestClass(TestContext testContext) throws Exception;
4.   
5.      void prepareTestInstance(TestContext testContext) throws Exception;
6.   
7.      void beforeTestMethod(TestContext testContext) throws Exception;
8.   
9.      void afterTestMethod(TestContext testContext) throws Exception;
10.             
11.                void afterTestClass(TestContext testContext) throws Exception;
12.            }

单测一般不需要显示的配置@TestExecutionListeners注解,默认@ContextConfiguration会自动注册如下Spring Test自带的TestExecutionListener

1.  org.springframework.test.context.web.ServletTestExecutionListener
2.  org.springframework.test.context.support.DependencyInjectionTestExecutionListener
3.  org.springframework.test.context.support.DirtiesContextTestExecutionListener
4.  org.springframework.test.context.transaction.TransactionalTestExecutionListener
5.  org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener

可以看到,Spring Test很多方便的功能都是通过TestExecutionListener来实现的,比如说DependencyInjectionTestExecutionListener来为单测类实例进行依赖注入的

1.  public class DependencyInjectionTestExecutionListener extends AbstractTestExecutionListener {
2.   
3.      @Override
4.      public void prepareTestInstance(final TestContext testContext) throws Exception {
5.          if (logger.isDebugEnabled()) {
6.              logger.debug("Performing dependency injection for test context [" + testContext + "].");
7.          }
8.          injectDependencies(testContext);
9.      }
10.             
11.                protected void injectDependencies(final TestContext testContext) throws Exception {
12.                    Object bean = testContext.getTestInstance();
13.                    AutowireCapableBeanFactory beanFactory = testContext.getApplicationContext().getAutowireCapableBeanFactory();
14.                    beanFactory.autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_NO, false);
15.                    beanFactory.initializeBean(bean, testContext.getTestClass().getName());
16.                    testContext.removeAttribute(REINJECT_DEPENDENCIES_ATTRIBUTE);
17.                }
18.             
19.            }

在单测中经常会使用到Mockito的注解,所以可以在单测基础类中使用Mockito的Rule,这样子类就可以使用Mockito的注解了

1.  @RunWith(SpringJUnit4ClassRunner.class)
2.  @ContextConfiguration("classpath:base-context.xml")
3.  public class XXXTestBase {
4.      @Rule
5.      public MockitoRule rule = MockitoJUnit.rule();
6.  }
7.   
8.  @ContextConfiguration("classpath:extended-context.xml")
9.  public class YYYTest extends XXXTestBase{
10.             
11.                @Resource
12.                @@InjectMocks
13.                private SpringXXXBean xxxBean;
14.             
15.                @Mock
16.                private XXXHsfBean xxxHsfBean
17.             
18.            }

在执行单测时,涉及到数据库操作时经常要在单测方法执行前在数据库中准备好单测数据,Spring Test提供了非常方便的注解来在单测方法前初始化数据,如下所示

1.  @RunWith(SpringRunner.class)
2.  @ContextConfiguration(locations = "classpath:spring-test-root.xml")
3.  public class BTestClass {
4.   
5.      @Resource
6.      private TestMapper mapper;
7.   
8.      @Test
9.      @Sql("BTestClass_testAAA.sql")
10.                //默认会在BTestClass相同的目录下查找BTestClass_testAAA.sql文件执行
11.                public void testAAA() {
12.                    List<TestModel> all = mapper.getAll();
13.             
14.                    Assert.isTrue(all != null && all.size() == 1);
15.                }
16.             
17.            }

@Sql注解可以注解在类上,表示每个单测方法前都执行该SQL脚本,但是要注意单测方法插入到数据库的记录默认并不会在单测执行完后回滚,所以如果SQL脚本中有插入操作,容易出现主键冲突,因为脚本会在每次单测执行时都执行

@Sql可以指定脚本的执行时机,如在单测方法执行前或执行后,通过executionPhase参数控制

在单测时,可能某些单测只能依赖MySQL,可以通过Spring的Profile功能来实现默认使用H2,但可以通过注解的方式来显示给某些单测指使用MYSQL数据源

1.  <?xml version="1.0" encoding="UTF-8"?>
2.  <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
3.      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
4.              http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
5.              http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
6.              http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
7.              http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.2.xsd">
8.   
9.      <beans profile="H2">
10.                    <jdbc:embedded-database id="dataSource" generate-name="true" type="H2">
11.                        <jdbc:script location="classpath:/sql/test_schema.sql" />
12.                    </jdbc:embedded-database>
13.                </beans>
14.             
15.                <beans profile="MYSQL">
16.                    <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
17.                        <property name="url" value="${db.url}" />
18.                        <property name="username" value="${db.username}" />
19.                        <property name="password" value="${db.password}" />
20.                        <!-- mysql jdbc 6.0driver改包名了 -->
21.                        <property name="driverClassName" value="${db.driver.class}" />
22.                        <property name="initialSize" value="1" />
23.                        <property name="maxActive" value="50" />
24.                        <property name="minIdle" value="1" />
25.                        <property name="maxWait" value="60000" />
26.                        <property name="testOnBorrow" value="false" />
27.                        <property name="testOnReturn" value="false" />
28.                        <property name="testWhileIdle" value="true" />
29.                        <property name="timeBetweenEvictionRunsMillis" value="60000" />
30.                        <property name="minEvictableIdleTimeMillis" value="25200000" />
31.                        <property name="removeAbandoned" value="true" />
32.                        <property name="removeAbandonedTimeout" value="1800" />
33.                        <property name="logAbandoned" value="true" />
34.                        <property name="filters" value="mergeStat" />
35.                    </bean>
36.                </beans>
37.             
38.            </beans>
39.            @RunWith(SpringRunner.class)
40.            @ContextConfiguration(locations = "classpath:spring-test-root.xml")
41.            @ActiveProfiles(profiles = "H2", inheritProfiles = false)
42.            public class BaseTest {
43.             
44.                @Rule
45.                public MockitoRule rule = MockitoJUnit.rule();
46.             
47.            }
48.             
49.            @ActiveProfiles(profiles = "MYSQL", inheritProfiles = false)
50.            public class BTestClass extends BaseTest {
51.             
52.                @Resource
53.                private TestMapper mapper;
54.             
55.                @Test
56.                @Sql("BTestClass_testAAA.sql")
57.                public void testAAA() {
58.                    List<TestModel> all = mapper.getAll();
59.             
60.                    Assert.isTrue(all != null && all.size() == 1);
61.                }
62.             
63.            }

可以通过Spring元注解功能来使代码更语义化一些

1.  /**
2.   * 选择使用H2数据库还是使用Mysql数据库, 底层使用的是SpringProfile功能
3.   * 
4.   * 可以通过
5.   * 
6.   * @see spring-test-datasource.xml
7.   * @author tudesheng
8.   * @since 2016913下午7:02:38
9.   *
10.             */
11.            @Documented
12.            @Inherited
13.            @Retention(RetentionPolicy.RUNTIME)
14.            @Target(ElementType.TYPE)
15.            @ActiveProfiles(inheritProfiles = false)
16.            public @interface DBSelecter {
17.             
18.                /**
19.                 * profiles, 取值只能是DBTypes.H2, 或者是DBTypes.MYSQL, 默认DBTypes.H2
20.                 */
21.                @AliasFor(annotation = ActiveProfiles.class, attribute = "profiles")
22.                String[] value() default { DBTypes.H2 };
23.             
24.                /**
25.                 * profiles, 取值只能是DBTypes.H2, 或者是DBTypes.MYSQL, 默认DBTypes.H2
26.                 */
27.                @AliasFor(annotation = ActiveProfiles.class, attribute = "profiles")
28.                String[] type() default { DBTypes.H2 };
29.             
30.            }
31.             
32.            @RunWith(SpringRunner.class)
33.            @ContextConfiguration(locations = "classpath:spring-test-root.xml")
34.            @DBSelecter(DBTypes.H2)
35.            public class BaseTest {
36.             
37.                @Rule
38.                public MockitoRule rule = MockitoJUnit.rule();
39.             
40.            }
41.             
42.            @DBSelecter(DBTypes.MYSQL)
43.            public class BTestClass extends BaseTest {
44.             
45.                @Resource
46.                private TestMapper mapper;
47.             
48.                @Test
49.                @Sql("BTestClass_testAAA.sql")
50.                public void testAAA() {
51.                    List<TestModel> all = mapper.getAll();
52.             
53.                    Assert.isTrue(all != null && all.size() == 1);
54.                }
55.             
56.            }

在使用MYSQL等外部数据库时,单测的执行很容易产生脏数据,可以通过@Rollback注解来标注单测方法执行完后,回滚数据库操作,减少对外部测试数据库的污染

最后,某些单测方法执行后可能会污染Spring的上下文,比如通过反射将某个容器内的Bean的属性给替换调了,可能会对其它的单测造成影响,这个时候,可以通过@DirtiesContext标注该单测方法会污染Spring上下文,需要在单测执行前或执行后重新初始化Spring上下文,慎用,容易增加单测的执行时间

原文地址:https://www.cnblogs.com/Aaron-007/p/10438236.html

时间: 2024-11-06 10:00:25

单元测试基础知识(三)的相关文章

20_Shell语言———VIM编辑器基础知识三之窗口属性定制、配置文件及查找替换功能

Vim编辑器可以让用户按照需求来定制一些使用属性. 一.窗口属性定义 1)显示行号 行号不是内容,只是用来帮助用户确认文本所在的行.在vim编辑器中,如果要显示行号,可以在末行模式下输入: set number 如果想关闭,则可以在功能名称前面加上no,即: set nonumber 命令可以被简写,如set number 可以简写为 set nu:set nonumber 可以简写为 set nonu. 注意,上述设定仅对当前vim的进程有效,一旦当前进程关闭,这些设定就会失效,如果要使设定永

计算机科学基础知识(三)静态库和静态链接

三.将relocatable object file静态链接成可执行文件 将relocatable object file链接成可执行文件分成两步,第一步是符号分析(symbol resolution),第二步是符号重新定位(Relocation).本章主要描述这两个过程,为了完整性,静态库的概念也会在本章提及. 1.为什么会提出静态库的概念? 程序逻辑有共同的需求,例如数学库.字符串库等,如果每个程序员在撰写这些代码逻辑的时候都需要自己重新写那么该是多么麻烦的事情,而且容易出错,如果有现成的,

Dapper基础知识三

在下刚毕业工作,之前实习有用到Dapper?这几天新项目想用上Dapper,在下比较菜鸟,这块只是个人对Dapper的一种总结. Dapper,当项目在开发的时候,在没有必要使用依赖注入的时候,如何做到对项目的快速开发这里对Dapper做一个小的进阶. 结合上一篇的博客,就可以使用了. public class Demo { public string name { get; set; } public string DapperTest { get; set; } } public class

【基础知识三】线性模型

一.基本形式 通过属性的线性组合来进行预测, 许多非线性模型可以在线性模型的基础上,引入层级结构或高维映射而得. 二.线性回归 最小二乘法:求解ω和b: 多元线性回归:样本由多个属性描述,即x为多维向量: 若矩阵不满秩产生多个解,解决方法:引入正则化项: 三.对数/逻辑线性回归 广义线性模型: g(.)条件:连续且充分光滑(单调可微) 为了预测值连续,引入Sigmoid函数 得到, 极大似然估计:求解ω和b 四.线性判别分析LDA 也叫"Fisher判别" 将样例投影到一条直线上,使同

KnockoutJS基础知识(三)

对于knockoutJS来讲,模板绑定和Mapping插件绑定是十分重要的功能,虽然模板绑定在我工作中用的及其少,但模板绑定的重要性不可忽视,在其他前端框架中,如Angular.Vue等等,模板存在的意义十分重要,Mapping插件使得我们能够脱离手工绑定,及其方便我们快速绑定达到预期效果. KnockoutJS模型绑定更多用法:https://knockoutjs.com/documentation/template-binding.html 本文地址:https://www.cnblogs.

单元测试基础知识(二)

6 单元测试设计原则和任务 6.1 三原则 为了提高开发人员的代码质量,编写高质量的单元测试,要遵守3R(Responsible, Reliable, Repeative)原则,具体含义如下: Responsible: 谁开发谁负责测试,在哪里开发就在哪里测试. Reliable: 测试case要可靠,并且是值得信赖的,对于底层的任何改动都要能够及时感知. Repeative: 所有单元测试用例都要能够重复运行.能够重复运行就能够进行回归测试.覆盖率统计等等. 6.2 单元测试任务 一般来说,单

3. K线基础知识三

1. 阴线 证券市场上指开盘价高于收盘价的K线,K线图上一般用淡蓝色标注,表示股价下跌,当收盘价低于开盘价,也就是股价走势呈下降趋势时,我们称这种形态的K线为阴线. 中间部分实体为蓝色,此时,上影线的长度表示最高价和开盘价之间的价差.实体的长短代表开盘价比收盘价高出的幅度.下影线的长度则有收盘价和最高价之间的价差大小所决定. 2. 小阴星 小阴星的分时走势图与小阳星相似,只是收盘价格略低于开盘价格.表明行情疲软,发展方向不明. 3. 小阴线 表示空方呈打压态势,但力度不大. 4. 光脚阴线 光脚

Linux基础知识三

1.列出当前系统上所有已经登录的用户的用户名,注意:同一个用户登录多次,则只显示一次即可. 查看系统用户的命令为: (1)getent passwd 查看系统上的所有用户信息 (2)w 查看登录用户正在使用的进程信息,该命令所使用的信息来源于/var/run/utmp文件 w命令输出的信息包括: -用户名称 -用户的机器名称或tty号 -远程主机地址 -用户登录系统的时间 -空闲时间(作用不大) -附加到tty(终端)的进程所用的时间(JCPU时间) -当前进程所用时间(PCPU时间) -用户当

单元测试基础知识

本人博客文章网址:https://www.peretang.com/basic-knowledge-of-unit-testing/ 什么是单元测试 单元测试, 用于验证你的应用程序是否可以按照预期的方式正常运行. 主要通过Mock或者Stub机制来隔绝与其他组件/服务之间的依赖, 控制测试的边界, 从而针对一个个单独的类或方法进行代码检查与测试. 为什么需要单元测试 因为每个单元(类或方法)都是整个系统的基石. 当实施单元测试时, 虽然短期来会对生产效率造成影响, 但是由于实施单元测试后, 项