当前位置: 首页 > news >正文

河南省建设厅官方网站网站建设客户需求分析

河南省建设厅官方网站,网站建设客户需求分析,进口全屋定制十大名牌,网站开发计划Angular_单元测试 测试分类 按开发阶段划分按是否运行划分按是否查看源代码划分其他ATDD,TDD,BDD,DDD ATDDTDDBDDDDDAngular单元测试 Karma的介绍jasmine介绍单元测试的好处使用jasmine和karma创建一个Angular项目Karma配置Test.ts文件测试体验测试Form测试服务service常用断言…  Angular_单元测试 测试分类 按开发阶段划分按是否运行划分按是否查看源代码划分其他ATDD,TDD,BDD,DDD ATDDTDDBDDDDDAngular单元测试 Karma的介绍jasmine介绍单元测试的好处使用jasmine和karma创建一个Angular项目Karma配置Test.ts文件测试体验测试Form测试服务service常用断言方法Mock Mock服务实例 Angular_单元测试 测试分类 按开发阶段划分 单元测试 单元测试又称模块测试针对软件设计中的最小单位——程序模块进行正确性检查的测试工作。集成测试 集成测试又叫组装测试通常在单元测试的基础上将所有程序模块进行有序的、递增测试。重点测试不同模块的接口部分系统测试 指的是将整个软件系统看成一个整体进行测试包括对功能、性能以及软件所运行的软硬件环境进行测试。验收测试 指按照项目任务书或合同、供需双方约定的验收依据文档进行的对整个系统的测试与评审决定是否接收或拒收系统按是否运行划分 静态测试 是指不实际运行被测软件而只是静态地检查程序代码、界面或文档中可能存在的错误过程动态测试 是指实际运行被测程序输入相应的测试数据检查实际输出结果和预期结果是否相符的过程。按是否查看源代码划分 黑盒测试 指的是把被测的软件看做一个黑盒子不关心盒子里面的结构是什么样子只关心软件的输入数据和输出数据。白盒测试 指的是把盒子打开去研究里面的源代码和程序结构。其他 回归测试 是指软件被修改后重新进行的测试重复执行上一个版本测试时的用例是为了保证对软件所做的修改没有引入新的错误而重复进行的测试。冒烟测试 是指在对一个新版本进行系统大规模的测试之前先验证一下软件的基本功能是否实现是否具备可测性。随机测试 是指测试中所有的输入数据都是随机生成的其目的是模拟用户的真实操作并发现一些边缘性的错误。ATDD,TDD,BDD,DDD ATDD ATDD Acceptance Test Driven Development验收测试驱动开发 TDD 只是开发人员的职责通过单元测试用例来驱动功能代码的实现。在准备实施一个功能或特性之前首先团队需要定义出期望的质量标准和验收细则以明确而且达成共识的验收测试计划包含一系列测试场景来驱动开发人员的TDD实践和测试人员的测试脚本开发。面向开发人员强调如何实现系统以及如何检验。 TDD TDD Test-driven development 测试驱动开发 是一种使用自动化单元测试来推动软件设计并强制依赖关系解耦的技术。使用这种做法的结果是一套全面的单元测试可随时运行以提供软件可以正常工作的反馈。 测试驱动开发是敏捷开发中的一项核心实践和技术也是一种设计方法论。TDD的原理是在开发功能代码之前先编写单元测试用例代码测试代码确定需要编写什么产品代码。TDD的基本思路就是通过测试来推动整个开发的进行但测试驱动开发并不只是单纯的测试工作而是把需求分析设计质量控制量化的过程。TDD首先考虑使用需求对象、功能、过程、接口等主要是编写测试用例框架对功能的过程和接口进行设计而测试框架可以持续进行验证。。 BDD BDD:Behavior-Driven Development (行为驱动开发) 行为驱动开发是一种敏捷软件开发的技术它鼓励软件项目中的开发者、QA和非技术人员或商业参与者之间的协作。主要是从用户的需求出发强调系统行为。BDD最初是由Dan North在2003年命名它包括验收测试和客户测试驱动等的极限编程的实践作为对测试驱动开发的回应。 DDD DDD领域驱动开发Domain Drive Design DDD指的是Domain Drive Design也就是领域驱动开发,DDD实际上也是建立在这个基础之上因为它关注的是Service层的设计着重于业务的实现,将分析和设计结合起来不再使他们处于分裂的状态这对于我们正确完整的实现客户的需求以及建立一个具有业务伸缩性的模型。 Angular单元测试 Unit Test(单元测试) 对正式的项目进行单元测试是必须的如果选择使用TDD(测试驱动开发)方法则无关紧要否则使用它将会产生很多好处。 在本文中我们首先简单地提到单元测试的好处然后我们将创建一个Angular单元测试的完整示例使用jasmine和karma。 Karma的介绍 Karma是Testacular的新名字在2012年google开源了Testacular2013年Testacular改名为Karma。Karma是一个让人感到非常神秘的名字表示佛教中的缘分因果报应比Cassandra这种名字更让人猜不透 Karma是一个基于Node.js的JavaScript测试执行过程管理工具Test Runner。该工具可用于测试所有主流Web浏览器也可集成到CIContinuous integration工具也可和其他代码编辑器一起使用。这个测试工具的一个强大特性就是它可以监控(Watch)文件的变化然后自行执行通过console.log显示测试结果。 jasmine介绍 TDD(Test Driven Development)测试驱动开发是敏捷开发中提出的最佳实践之一。jasmine很有意思的提出了BDD(Behavior Driven Development)行为驱动开发. 测试驱动开发对软件质量起到了规范性的控制。未写实现先写测试一度成为Java领域研发的圣经。随着Javascript兴起功能越来越多代码量越来越大开发人员素质相差悬殊真的有必要建立对代码的规范性控制。jasmine就是为团队合作而生。 Jasmine是一个用来编写Javascript测试的框架它不依赖于任何其它的javascript框架也不需要对DOM。它有拥有灵巧而明确的语法可以让你轻松的编写测试代码。 jasmine的结构很简单 describe(A suite, function() {var foo;beforeEach(function() {foo 0;foo 1;});afterEach(function() {foo 0;});it(contains spec with an expectation, function() {expect(true).toBe(true);}); }); 每个测试都在一个测试集中运行Suite就是一个测试集用describe函数封装。 Spec表示每个测试用例用it函数封装。通过expect函数作为程序断言来判断相等关系。setup过程用beforeEach函数封装tearDown过程用afterEach封装。 单元测试的好处 我们先来看看我认为在解决方案中使用单元测试的主要原因… 改进实现的设计 开始编写一个功能而不给设计带来太多的思考是开发人员非常常见的错误。使用单元测试将强制思考并重新考虑设计如果您使用TDD则影响会更大。 允许重构 既然你已经有测试确保你所有的东西都能按预期工作你可以很容易地添加对代码的修改确保你没有添加任何错误。 添加新功能而不会破坏任何内容 当您添加新功能时您可以运行测试以确保您不会破坏应用程序的任何其他部分。 还有更多但这三个在任何项目上都是如此巨大的胜利对于我来说这些赢利是封闭式的。但如果你不相信让我们再提几个。 测试是很好的文档。测试使开发人员对他们的工作更有信心。你可以说他们所有的好处都是以很高的成本来实现的但是这完全是错误的。所有使用单元测试可能花费的时间与以后在您引入新功能或进行任何重构时要节省的时间相比将会很小。花在解决错误上的时间要比没有使用单元测试时大大缩短。 我们将创建一个使用AngularJasmine和Karma的应用程序的小而完整的例子。 这些是我们要谈论的一些事情 解释一下工具Karma和Jasmine解释karma配置解释test文件创建第一个简单的测试,介绍Jasmine和Angular测试功能测试一个Angular form,介绍Jasmine和Angular测试功能测试一个带服务的组件介绍Angular测试功能使用jasmine和karma创建一个Angular项目 正如Angular团队建议我们要用Angular cli来创建我们的应用程序。通过这样做jasmine和karma的配置可以帮我们解决比较方便。 安装angular-cli并创建一个新项目 npm install -g angular/cling new UnitTest –routing当你创建项目时所有的依赖关系都会安装包括你需要创建测试的所有东西。 types/jasmine: ~2.8.6,types/jasminewd2: ~2.0.3,types/node: ~8.9.4,codelyzer: ~4.2.1,jasmine-core: ~2.99.1,jasmine-spec-reporter: ~4.2.1,karma: ~1.7.1,karma-chrome-launcher: ~2.2.0,karma-coverage-istanbul-reporter: ~1.4.2,karma-jasmine: ~1.1.1,karma-jasmine-html-reporter: ^0.2.2, jasmine-core:Jasmine是我们将用来创建测试的框架。它有许多功能可以让我们编写不同类型的测试。karma:Karma是我们测试的任务跑步者。它使用配置文件来设置启动文件报告测试框架浏览器等等。其余依赖主要为记录我们的测试工具使用karma和jasmine和browser的发射器。要运行测试只需运行命令“ng test”。该命令将执行测试打开浏览器显示控制台和浏览器报告同样重要的是将测试执行保留为监视模式。也就是当我们修改过后可以自动更新测试结果。 ng test 提示如果想要终止需要在终端内按CTRLC Karma配置 让我们来看看由angular-cli创建的karma配置文件。 // Karma configuration file, see link for more information // https://karma-runner.github.io/1.0/config/configuration-file.htmlmodule.exports function (config) {config.set({basePath: ,frameworks: [jasmine, angular-devkit/build-angular],plugins: [require(karma-jasmine),require(karma-chrome-launcher),require(karma-jasmine-html-reporter),require(karma-coverage-istanbul-reporter),require(angular-devkit/build-angular/plugins/karma)],client: {clearContext: false // leave Jasmine Spec Runner output visible in browser},coverageIstanbulReporter: {dir: require(path).join(__dirname, ../coverage),reports: [html, lcovonly],fixWebpackSourcePaths: true},reporters: [progress, kjhtml],port: 9876,colors: true,logLevel: config.LOG_INFO,autoWatch: true,browsers: [Chrome],singleRun: false}); }; 你大概可以猜到这些配置属性的大部分用途但我们来看看其中的一些。 frameworks:这是jasmine被设定为测试框架的地方。如果你想使用另一个框架这是做这件事的地方。reporters:负责将测试结果告知给开发者。通常是将结果打印到控制台上或者存入文件中autoWatch:如果设置为true则测试将以Watch模式运行。如果您更改任何测试并保存文件测试将重新生成并重新运行。browsers:这是您设置测试应该运行的浏览器的位置。默认情况下是chrome但你可以安装和使用其他浏览器启动器。Test.ts文件 karma的angular-cli配置使用文件“test.ts”作为应用程序测试的入口点。我们来看看这个文件; // This file is required by karma.conf.js and loads recursively all the .spec and framework filesimport zone.js/dist/zone-testing; import { getTestBed } from angular/core/testing; import {BrowserDynamicTestingModule,platformBrowserDynamicTesting } from angular/platform-browser-dynamic/testing;declare const require: any;// First, initialize the Angular testing environment. getTestBed().initTestEnvironment(BrowserDynamicTestingModule,platformBrowserDynamicTesting() ); // Then we find all the tests. const context require.context(./, true, /\.spec\.ts$/); // And load the modules. context.keys().map(context);你可能永远不需要改变这个文件但是有时候还是会更改的比如某一个spec文件排除测试等。 测试体验 我们来创建我们的第一个测试。修改app.component.ts。这个组件只有一个属性“text”其值为“Angular Unit Testing”它是在HTML中的“h1”标记中呈现的它还包含路由根元素和一些路由链接。让我们创建一个测试文件来检查组件是否实际具有该属性并且实际上是在HTML中呈现的。 app.component.html文件 h1{{text}}/h1 router-outlet/router-outlet app.component.ts文件 import { Component } from angular/core;Component({selector: app-root,templateUrl: ./app.component.html,styleUrls: [./app.component.css] }) export class AppComponent {text Angular Unit Testing; } app.component.spec.ts文件 import { TestBed, async } from angular/core/testing; import { RouterTestingModule } from angular/router/testing; import { AppComponent } from ./app.component; describe(AppComponent, () {beforeEach(async(() {TestBed.configureTestingModule({imports: [RouterTestingModule],declarations: [AppComponent],}).compileComponents();}));it(should create the app, async(() {const fixture TestBed.createComponent(AppComponent);const app fixture.debugElement.componentInstance;expect(app).toBeTruthy();}));it(should have as title app, async(() {const fixture TestBed.createComponent(AppComponent);const app fixture.debugElement.componentInstance;expect(app.text).toEqual(Angular Unit Testing);}));it(should render title in a h1 tag, async(() {const fixture TestBed.createComponent(AppComponent);fixture.detectChanges();const compiled fixture.debugElement.nativeElement;expect(compiled.querySelector(h1).textContent).toContain(Welcome to Angular Unit Testing!);})); });此时执行 ng test 或 npm test ng test的常用参数. - –code-coverage -cc 代码覆盖率报告, 默认这个是不开启的, 因为生成报告的速度还是比较慢的. - –colors 输出结果使用各种颜色 默认开启 - –single-run -sr 执行测试, 但是不检测文件变化 默认不开启 - –progress 把测试的过程输出到控制台 默认开启 - –sourcemaps -sm 生成sourcemaps 默认开启 - –watch -w 运行测试一次, 并且检测变化 默认开启 在弹出的chrome浏览器窗口中显示 我们详细介绍一下这个测试代码 导入测试文件的所有依赖项 这里要注意你在组件内使用的依赖这里面同样需要导入否则会无法运行。 使用describe开始我们的测试 describe是一个函数,Jasmine 就是使用 describe 全局函数来测试的。 declare function describe(description: string, specDefinitions: () void): void; 表示分组类似测试套也就是一组测试用例支持description嵌套。 例子 describe(测试显示/隐藏筛选条件, (){ }) 我们在每个之前使用异步。异步的目的是让所有可能的异步代码在继续之前完成Jasmine 就是使用 it 全局函数来表示和 describe 类似字符串和方法两个参数。 每个 Spec 内包括多个 expectation 来测试需要测试的代码只要任何一个 expectation 结果为 false 就表示该测试用例为失败状态。describe(demo test, () {const VALUE true;it(should be true, () {expect(VALUE).toBe(VALUE);}) }); 如果有很多需要测试的可以多个it describe(AppComponent, () {beforeEach(async(() {TestBed.configureTestingModule({imports: [RouterTestingModule],declarations: [AppComponent],}).compileComponents();}));it(should create the app, async(() {const fixture TestBed.createComponent(AppComponent);const app fixture.debugElement.componentInstance;expect(app).toBeTruthy();})); }); 断言使用 expect 全局函数来表示只接收一个代表要测试的实际值并且需要与 Matcher 代表期望值。 TestBed可以帮助我们创建app实例 代码中有3个it 第一个为异步测试app是否true或false 如果app是0两次取反当然是false 如果app是null两次取反是false 如果app是undefined两次取法是false 其余的两次取反是true 第二个为异步测试app是否有text属性并且判断值是否和预期相同 第三个为异步测试app是否在h1标签中的显示值为预期值测试Form 创建一个contact组件。ng g c contact 首先我们修改contact.component HTML文件div{{text}}/divform idcontact-form [formGroup]contactForm (ngSubmit)onSubmit() novalidatediv classform-grouplabel classcenter-blockName:input classform-control formControlNamename/labellabel classcenter-blockEmail:input classform-control formControlNameemail/labellabel classcenter-blockText:input classform-control formControlNametext/label/divbutton typesubmit[disabled]!contactForm.valid classbtn btn-successSave/button/form这很简单针对代码不做任何解释了。 修改contact.component.ts文件import { Component, OnInit } from angular/core; import { FormGroup, FormControl, Validators } from angular/forms;Component({selector: app-contact,templateUrl: ./contact.component.html,styleUrls: [./contact.component.css] }) export class ContactComponent {text contact page;contactForm: FormGroup;contact {name: ,email: ,text: };submitted false;constructor() {this.createForm();}createForm(): void {this.contactForm new FormGroup({name: new FormControl(this.contact.name, [Validators.required,Validators.minLength(4)]),email: new FormControl(this.contact.email, [Validators.required,Validators.email]),text: new FormControl(this.contact.text, Validators.required)});}onSubmit(): void {this.submitted true;} } 这个组件也很容易理解。 onSubmit提交函数只是将提交的属性更改为true。 修改app-routing.module.tsimport { ContactComponent } from ./contact/contact.component; import { NgModule } from angular/core; import { Routes, RouterModule } from angular/router;const routes: Routes [{path: ,redirectTo: contact,pathMatch: full},{path: contact,component: ContactComponent} ];NgModule({imports: [RouterModule.forRoot(routes)],exports: [RouterModule] }) export class AppRoutingModule { }此时终端执行 npm start 修改测试文件contact.component.spec.tsimport { BrowserModule, By } from angular/platform-browser; import { async, ComponentFixture, TestBed } from angular/core/testing;import { ContactComponent } from ./contact.component; import { DebugElement } from angular/core; import { FormsModule, ReactiveFormsModule } from angular/forms;describe(ContactComponent, () {let comp: ContactComponent;let fixture: ComponentFixtureContactComponent;let de: DebugElement;let el: HTMLElement;beforeEach(async(() {TestBed.configureTestingModule({declarations: [ContactComponent],imports: [BrowserModule,FormsModule,ReactiveFormsModule]}).compileComponents().then(() {fixture TestBed.createComponent(ContactComponent);comp fixture.componentInstance;de fixture.debugElement.query(By.css(form));el de.nativeElement;});}));it(should have as text contact page, async(() {expect(comp.text).toEqual(contact page);}));it(should set submitted to true, async(() {comp.onSubmit(); // 直接内部调用onSubmit函数 submitted被更改为trueexpect(comp.submitted).toBeTruthy();}));it(form call the onSubmit method, async(() {fixture.detectChanges();spyOn(comp, onSubmit);el fixture.debugElement.query(By.css(button)).nativeElement;el.click(); // 模拟在html界面上点击onSubmit此时是不能被点击的因为没有输入所以次数应该是0expect(comp.onSubmit).toHaveBeenCalledTimes(0);}));it(form should be invalid, async(() {comp.contactForm.controls[email].setValue();comp.contactForm.controls[name].setValue();comp.contactForm.controls[text].setValue();expect(comp.contactForm.valid).toBeFalsy();}));it(form should be vaild, async(() {comp.contactForm.controls[email].setValue(asdasd.com);comp.contactForm.controls[name].setValue(aada);comp.contactForm.controls[text].setValue(text);expect(comp.contactForm.valid).toBeTruthy();})); });此时执行 ng test 我们来分析一下这个测试文件做了哪些东西 导入依赖模块BrowserModule,FormsModule,ReactiveFormsModule使用”By”将DOM中的form导入进来第一个测试text属性测试onSubmit函数调用第三个测试使用“fixture”对象的函数“detectChanges”将组件状态应用于HTML然后从DOM获取提交按钮并触发单击事件。在此之前我们在组件的“onSubmit”功能上创建一个jasmine “spy”。最后我们期望onSubmit函数不会被执行因为这个按钮应该被禁用因为表单无效。第四个测试将无效值设置为组件表单并期望表单有效属性为false。最后在第五个测试中我们将有效值设置为表单并期望表单有效属性为真。小提示 - detectChanges 在测试中的Angular变化检测。每个测试程序都通过调用fixture.detectChanges()来通知Angular执行变化检测。 - By By类是Angular测试工具之一它生成有用的predicate。 它的By.css静态方法产生标准CSS选择器 predicate与JQuery选择器相同的方式过滤。 测试服务service 当你要测试一个带有服务的组件时就像我们已经看到的那样你需要将提供者添加到在“beforeEach”中创建的测试模块。事情是你可能不想使用实际的服务而是一个模拟版本所以让我们看看如何做到这一点…… 创建一个app.service服务ng g s app 修改app.service.tsimport { Injectable } from angular/core;Injectable({providedIn: root }) export class AppService {constructor() { }getInfo(): string {return test service;} } 修改app.component.tsimport { AppService } from ./app.service; import { Component } from angular/core;Component({selector: app-root,templateUrl: ./app.component.html,styleUrls: [./app.component.css] }) export class AppComponent {text Angular Unit Testing;info: string;constructor(private service: AppService) {this.info this.service.getInfo();} } 在app.component.spec.ts内增加 注意引入AppService服务。...providers: [AppService] ...it(should have as info test service, async(() {const fixture TestBed.createComponent(AppComponent);const app fixture.debugElement.componentInstance;expect(app.info).toEqual(test service);})); 修改app.service.spec.tsimport { TestBed, inject, async } from angular/core/testing;import { AppService } from ./app.service;describe(AppService, () {beforeEach(() {TestBed.configureTestingModule({providers: [AppService]});});it(should be created, inject([AppService], (service: AppService) {expect(service).toBeTruthy();}));it(should getInfo test service, inject([AppService], (service: AppService) {expect(service.getInfo()).toEqual(test service);})); });此时执行 ng test 测试全部通过。 小提示 有些时候我们希望不是异步的这时需要使用takeAsync函数fakeAsync最重要的好处是测试程序看起来像同步的。 it(should show quote after getQuote promise (fakeAsync), fakeAsync(() {fixture.detectChanges();tick(); // wait for async getQuotefixture.detectChanges(); // update view with quoteexpect(el.textContent).toBe(testQuote); })); 常用断言方法 Jasmine 提供非常丰富的API一些常用的Matchers toBe() 等同 toNotBe() 等同 !toBeDefined() 等同 ! undefinedtoBeUndefined() 等同 undefinedtoBeNull() 等同 nulltoBeTruthy() 等同 !!objtoBeFalsy() 等同 !objtoBeLessThan() 等同 toBeGreaterThan() 等同 toEqual() 相当于 toNotEqual() 相当于 !toContain() 相当于 indexOftoBeCloseTo() 数值比较时定义精度先四舍五入后再比较。toHaveBeenCalled() 检查function是否被调用过toHaveBeenCalledWith() 检查传入参数是否被作为参数调用过toMatch() 等同 new RegExp().test()toNotMatch() 等同 !new RegExp().test()toThrow() 检查function是否会抛出一个错误而这些API之前用 not 来表示负值的判断。 expect(true).not.toBe(false); 这些Matchers几乎可以满足我们日常需求当然你也可以定制自己的Matcher来实现特殊需求。 Mock 在实际的组件测试中发现组件往往依赖于服务。而服务又依赖于外部资源如http交互、本地资源等。为了屏蔽外部依赖方便组件的测试可以对服务进行mock。对于服务的mock方式有两种伪造服务实例提供服务复制品、刺探真实服务。这两种方式都能够达到mock的效果我们可以挑选一种最适合自己当前测试文件的测试方式来进行测试。 Mock服务实例 第一步编写服务的mock类 class TaskMonitorStubService extends TaskMonitorService {public queryTaskList(request: ViewTaskRequest): Observableany {return request.code -1 ? Observable.of(runningTaskResponse): Observable.of(finishedTashResponse)} } 第二步在configureTestingModule用Mock的服务替换真实的服务 TestBed.configureTestingModule({imports: [HttpModule,TaskMonitorModule],Providers: [{provide: TaskMonitorService, useClass: TaskMonitorStubService}] }) 刺探真实服务 Angular的服务都是通过注入器注入到系统中的同样我们可以从根TestBed获取到注入服务的实例然后结合刺探Spy对真实的服务的方法进行替换. let taskMonitorService: TaskMonitorService TestBe.get(TaskMonitorService); spyOn(taskMonitorService, queryTaskList).and.returnValue(Observable.of(runningTaskResponse)); --------------------- 作者FlyWine 来源CSDN 原文https://blog.csdn.net/wf19930209/article/details/80413904 版权声明本文为作者原创文章转载请附上博文链接
http://www.zqtcl.cn/news/57830/

相关文章:

  • 宣城市网站集约化建设定制企业网站建设哪家好
  • app开发与网站开发大学生创业服务网站建设方案
  • wordpress 微信登陆网站怎样优化文章关键词
  • 亚马逊网站的建设和维护郑州哪家建设网站
  • 北京朝阳网站制作长沙 外贸网站建设
  • 浏览器网站建设的步骤过程泉州网站建设哪里好
  • seo网站关键词优化排名wordpress ms no
  • 网站专栏建设工作方案动态小网站
  • 响应式网站企业wordpress添加网站图标
  • 用ps做网站得多大像素由前台有后台的网站怎么做
  • 网站域名免费注册网站百度流量怎么做
  • 农村网站建设调查报告江苏商城网站制作公司
  • wordpress清楚缓存白城seo
  • 动易网站模板wordpress 联系我们 制作
  • windows优化大师官方网站制作和设计网页图
  • 网站页面分析范文深圳蕾奥规划设计公司网站
  • 网站建设-纵横网络网站建设方案设计
  • 扁平网站 文案网页游戏平台代理
  • 网站请及时续费成都住房和城乡建设局 网站首页
  • 什么是网站风格策划的重点网站模板手机
  • 有人有片视频吗免费的下载成都公司网站seo
  • 怎么创建卡密网站17.zwd一起做网站池尾站
  • 国外做油画的网站十大网站开发公司
  • 临安规划建设局网站个人app怎么做
  • 佛山新网站建设如何安徽省港航建设投资集团网站
  • 模拟建设网站网站制作培训多少钱
  • 做网站要不要签合同天使投资
  • 佛山网站建设哪个好申请免费域名的方法
  • 网站建设虚拟主机说明微信网页宣传网站怎么做的
  • 如何建立网站会员系统wordpress主题 kratos