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

知名企业网站分析 比较评估建设网站终身免费

知名企业网站分析 比较评估,建设网站终身免费,中国制造网服务种类,泰安集团网站建设方案在之前的文章里我们已经学习了Python自带测试框架UnitTest#xff0c;但是UnitTest具有一定的局限性 这篇文章里我们来学习第三方框架Pytest#xff0c;它在保留了UnitTest框架语法的基础上有着更多的优化处理 下面我们将从以下角度来介绍Pytest#xff1a; Pytest基本介绍…在之前的文章里我们已经学习了Python自带测试框架UnitTest但是UnitTest具有一定的局限性 这篇文章里我们来学习第三方框架Pytest它在保留了UnitTest框架语法的基础上有着更多的优化处理 下面我们将从以下角度来介绍Pytest Pytest基本介绍 Pytest基本使用 Pytest进阶内容 如果你想学习自动化测试我这边给你推荐一套视频这个视频可以说是B站播放全网第一的自动化测试教程同时在线人数到达1000人并且还有笔记可以领取及各路大神技术交流798478386    2023最新pytest接口自动化测试框架三天带你精通pytest带你写出最好的代码已更新2023新版_哔哩哔哩_bilibili2023最新pytest接口自动化测试框架三天带你精通pytest带你写出最好的代码已更新2023新版共计32条视频包括1、Pytest简介、2、Pytest之pytest测试用例的运行方式、3、Pytest之pytest执行测试用例的顺序是怎样的呢等UP主更多精彩视频请关注UP账号。https://www.bilibili.com/video/BV1py4y1t7bJ/?spm_id_from333.337.search-card.all.click Pytest基本介绍 下面我们首先来简单介绍Pytest及相关内容 单元测试框架 我们首先需要知道测试一般分为四个方面的测试 单元测试称模块测试针对软件设计中的最小单位——程序模块进行正确性检查的测试工作 集成测试称组装测试通常在单元测试的基础上将所有程序模块进行有序的、递增测试重点测试不同模块的接口部分 系统测试将整个软件系统看成一个整体进行测试包括对功能、性能以及软件所运行的软硬件环境进行测试 验收测试指按照项目任务书或合同、供需双方约定的验收依据文档进行的对整个系统的测试与评审决定是否接收或拒收系统 而我们这篇文章主要针对的是单元测试 Python通常使用UnitTest和Pytest来进行单元测试自动化但Pytest已经成为主流 Java通常使用Testng和Junit来进行单元测试自动化但Testng已经成为主流 最后我们需要明白单元测试框架的主要功能 发现测试用例 执行测试用例 判断测试结果 生成测试报告 框架基本介绍 下面我们来简单介绍Pytest框架 pytest是一个非常成熟的单元测试框架经过多版本的迭代主要优点在于灵活和简单 pytest具有极强的兼容性和生态环境它可以结合seleniumrequestsappium完成各种不同的自动化 pytest具有更好的页面展示效果它可以生成自定义allure报告以及和Jenkins持续集成 下面我们给出一些和Pytest框架可以很好聚合的框架类型 pytestpytest-html主要用来生成html报告的插件 pytest-xdist主要用来进行多线程运行的插件 pytest-ordering主要用来改变用例的执行顺序的插件 pytest-rerunfailres主要用来失败用例重跑的插件 allure-pytest主要用来生成美观自定义的allure报告 我们可以采用一种比较简便的方式来一次性下载这些框架 # 首先我们需要将这些名称全部放入一个txt文件中假设我们放在requestment.txt文件中# requestment.txt文件 pytest-html pytest-xdist pytest-ordering pytest-rerunfailures# 我们只需要在pycharm的console中输入指令下载该文件夹中全部内容即可 pip install -r requirements.txt Pytest基本使用 下面我们来介绍Pytest的基本使用 Pytest默认测试用例 下面我们首先讲解Pytest默认测试用例的格式 # 首先我们的模块名文件名通常被统一存放在一个testcases文件夹中然后需要保证模块名须以test_开头或者_test结尾 # 例如我们下面的模块名命名就是正确示例 test_demo1 demo2_test# 然后我们需要注意我们模块中的测试类类名必须以Test开头并且不能带有init方法 # 例如我们下面的类名命名就是正确示例 class TestDemo1: class TestLogin:# 最后我们需要注意我们测试类中的测试方法名Case名必须以test_开头 # 例如我们下面的模块名命名就是正确示例 test_demo1(self) test_demo2(self)# 我们给出一个测试用例例子 # 文件名为test_demo1 class TestDemo:def test_demo1(self):print(测试用例1)def test_demo2(self):print(测试用例2)# 当然我们上述的要求都不是必须相同的在后续我们可以进行修改我们将在下述讲解执行方法时讲解 然后我们再来讲解一下Pytest的测试用例该如何执行 # 首先我们讲解一下全局配置文件pytest.ini # 我们可以在pytest.ini中进行一些属性的配置来修改Pytest的默认属性我们需要在项目的根目录下创建名称必须是pytest.ini1 [pytest] 2 #参数 3 addopts ‐vs # 这里指当默认使用指令时的一些辅助参数我们后面会讲解 4 testpaths ./testcases # 这里指默认的执行路径它会默认执行该文件夹下所有的满足条件的测试case 5 python_files test_*.py # 这里就是前面我们所说的文件命名规则 6 python_classes Test* # 这里就是前面我们所说的类名命名规则 7 python_functions test_* # 这里就是前面我们所说的Case命名规则 8 #标记 9 markers # 这里是冒烟规则我们后面会讲到 10 smoke:冒烟用例 11 product_manage:商品管理 # 然后我们首先来讲采用console命令行执行Pytest的方法 # 最简单的就是直接在console命令行输入pytest如果存在pytest.ini它会根据文件内容进行执行如果没有就按照默认格式执行 # 但是我们可以通过一些参数来强化pytest参数指令# -vs-v输出详细信息 -s输出调试信息 pytest -vs# -n多线程运行前提安装插件pytest-xdist pytest -vs -n2# --reruns num: 失败重跑前提安装插件pytest-rerunfailres pytest -vs --reruns2# -x: 出现一个用例失败则停止测试 pytest -vs -x# --maxfail: 出现几个失败才终止 pytest -vs --maxfail2# --html: 生成html的测试报告,后面 需要跟上所创建的文件位置及文件名称前提安装插件pytest-html pytest -vs --html ./reports/result.html# -k运行测试用例名称中包含某个字符串的测试用例我们可以采用or表示或者采用and表示都 # 采用or就表示我们的运行用例名称中包含or两侧的其中一个数据即可 # 采用and就表示我们的运行用例名称中包含and两侧的所有数据才满足条件 pytest -vs -k qiuluo pytest -vs -k qiuluo or weiliang pytest -vs -k qiuluo and weiliang# -m冒烟用例执行后面需要跟一个冒烟名称 # 我们在这里简单介绍一下冒烟用例的执行方法我们这里其实就是一个分组执行的方法 # 例如我们的用例划分为user_manage用户管理测试和product_manage商品管理测试我们只希望执行其中一组测试# 首先我们需要在他们的不同方法上进行mark划分具体操作如下 class TestDemo:# 我们在Case上采用pytest.mark. 分组名称就相当于该方法被划分为该分组中# 注意一个分组可以有多个方法一个方法也可以被划分到多个分组中pytest.mark.user_managedef test_demo1(self):print(user_manage_test1)pytest.mark.product_managedef test_demo2(self):print(product_manage_test1)pytest.mark.user_managepytest.mark.product_managedef test_demo3(self):print(manage_test1)# 我们在执行中只需要采用前面我们所说的-m 分组名称即可 pytest -vs -m user_manage# 这里插一句我们在运行过程中可以采用抛出异常的方式来模拟测试失败raise Exception() 抛出异常# 最后我们也可以采用main方法来执行pytest同样我们也可以使用参数来进行调节 if __name__ __main__:pytest.main()if __name__ __main__:pytest.main([‐vs]) 最后我们插入一个简单的案例跳过方法 # pytest的跳过案例方法其实和unittest是完全相同的 # 我们只需要采用skip或skipif方法来指定参数并贴在方法上即可跳过# pytest.mark.skip(跳过原因)# pytest.mark.skipif(跳过条件,跳过原因)# 我们给出一个示例 class TestDemo:workage2 5workage3 20pytest.mark.skip(reason无理由跳过)def test_demo1(self):print(我被跳过了)pytest.mark.skipif(workage210,reason工作经验少于10年跳过) def test_demo2(self):print(由于经验不足我被跳过了)pytest.mark.skipif(workage310,reason工作经验少于10年跳过)def test_demo3(self):print(由于经验过关我被执行了)def test_demo3(self):print(我没有跳过条件所以我被执行了) Pytest前后置方法 首先我们需要先了解前后置是什么 前后置就是针对不同层级方法执行前和执行后所需要执行的步骤进行封装并执行 这个层级通常被划分为文件层类层方法层 首先我们先来介绍Pytest通过固件来实现前后置的方法 # 我们通常采用前后置来做一些方法前后的操作 # 如果我们采用方法层的前后置那么它会在每个方法执行前后去执行该内容 # 如果我们采用类层的前后置那么它会在调用这个类内所有方法的前后去执行该内容但是无论该类的方法执行多少次它只会调用一次 # 例如我们做login测试时我们只需要在开始测试时打开一次浏览器然后在测试结束时关闭一次浏览器那么我们就采用类的前后置 # 我们做login测试时为了保证前置操作不对后续Case有影响所以我们在执行方法前打开该网页执行方法后关闭该网页采用方法的前后置# Pytest的固件前后置其实和unittest是基本相同的 # 首先是方法级别的固件前后置 # 它是在每个测试方法(用例代码) 执行前后都会自动调用的结构 # 方法执行之前def setUp(self):每个测试方法执行之前都会执行pass # 方法执行之后def tearDown(self):每个测试方法执行之后都会执行pass# 然后是针对类级别的固件前后置 # 它是在每个测试类中所有方法执行前后 都会自动调用的结构(在整个类中执行之前或之后执行一次) # 需要注意类级别的固件前后置, 是一个类方法 # 类中所有方法之前classmethoddef setUpClass(cls):pass # 类中所有方法之后classmethoddef tearDownClass(cls):pass# 最后是针对模块级别的固件前后置 # 在每个代码文件执行前后执行的代码结构 # 需要注意模块级别的需要写在类的外边直接定义函数即可 # 代码文件之前def setUpModule():pass # 代码文件之后def tearDownModule():pass# 下面我们采用一个用户账户登录的用例来简单展示一下固件前后置import unittestclass TestLogin(unittest.TestCase):# 在执行该类前所需要调用的方法classmethoddef setUpClass(cls) - None:print(------打开浏览器)# 在执行该类后所需要调用的方法classmethoddef tearDownClass(cls) - None:print(------关闭浏览器)# 每个测试方法执行之前都会先调用的方法def setUp(self):print(输入网址......)# 每个测试方法执行之后都会调用的方法def tearDown(self) - None:print(关闭当前页面......)# 测试Case1def test_1(self):print(输入正确用户名密码验证码,点击登录 1)# 测试Case2def test_2(self):print(输入错误用户名密码验证码,点击登录 2) 然后我们还需要讲解一下Fixtrue实现前后置的方法 # 首先我们需要知道Fixtrue所实现的功能基本和固件所实现的功能是一样的但是会更加方便 # 首先我们给出Fixture的完整格式然后我们再分开介绍各个参数 pytest.fixture(scopeNone,autouseFalse,paramsNone,idsNone ,nameNone)# scope作用范围 # 参数主要有三种function函数class类package/session包# function在函数层面上执行前后置 # 我们通常采用yield进行前后置划分yield前是前置yield后是后置pytest.fixture(scopefunction)def exe_database_sql():print(执行SQL查询)yieldprint(关闭数据库连接) # 我们还可以通过yield或return去返回一些参数在方法中使用 # 但是需要注意yield返回参数后后置仍旧可以执行但是return返回参数后后置操作无法执行pytest.fixture(scopefunction)def exe_database_sql():print(执行SQL查询)yield success# return success 执行后无法执行后置操作print(关闭数据库连接) # 我们的方法在调用时可以直接使用exe_database_sql表示返回信息进行输出 def test_2(selfexe_database_sql):print(exe_database_sql)# class在类之前和之后执行pytest.fixture(scopeclass)def exe_database_sql():print(执行SQL查询)yieldprint(关闭数据库连接)# package/session在整个项目会话之前和之后执行pytest.fixture(scopesession)def exe_database_sql():print(执行SQL查询)yieldprint(关闭数据库连接)# autouse:是否自动启动 # 该参数默认为False我们可以将其修改为True # 该参数的功能主要在判断该固件是否在自定义范围内可以自动启动 # 若自动启动则所有方法在执行时都会自动执行该前后置但若为False则我们需要手动启动# 首先如果是自动启动则我们无需关心任何参数我们的所有方法都会自动调用pytest.fixture(scopefunctionautouesTrue)def exe_database_sql():print(执行SQL查询)yieldprint(关闭数据库连接)# 但若是关闭自动启动我们在不同的scope下有不同的调用方法pytest.fixture(scopefunctionautouesFlase)def exe_database_sql():print(执行SQL查询)yieldprint(关闭数据库连接)# scope function我们需要在方法后加上该Fixture方法名def test_2(selfexe_database_sql):print(exe_database_sql)# scope class我们需要在对应的类上添加pytest.mark.usefixtures(exe_database_sql)装饰器调用 pytest.mark.usefixtures(exe_database_sql) class TestDemo:pass# scope session:.一般会结合conftest.py文件来实现,我们后面再介绍# 还需要注意autouse仅限于在自己的类中使用上述方法如果要跨类使用那么我们也需要在conftest.py中配置# params:实现参数化配置 # 通常我们的脚本都是根据导出的yaml文件进行属性填充针对参数化我们后面再讲我们先将Fixture的参数化 # params通常后面跟上具体的数据(列表元组等)然后我们在调用时有固定的写法 # 首先我们需要在Fixture方法参数中定义一个request然后使用request.param来使用我们传递的params数据 class TestDemo:def read_yaml():return [胡桃,胡桃宝宝,胡桃厨]# 首先我们的参数需要获取数据paramsread_yaml()pytest.fixture(scopefunction,autouseFalse,paramsread_yaml())# 然后我们的Fixture方法需要一个request参数def exe_database_sql(request):print(执行SQL查询)# 我们通过request.param获取数据可以采用yield返回该数据yield request.paramprint(关闭数据库连接)# ids参数别名id # 不能单独使用必须和params一起使用作用是对参数起别名 # 我们在采用pytest进行测试数据输出时会有对应的方法调用n次该n次采用不同的params参数这个ids就是修改了console控制台展示数据 class TestDemo:def read_yaml():return [胡桃,胡桃宝宝,胡桃厨]# 当我们书写了ids我们的控制输出就不会再是上面的[胡桃,胡桃宝宝,胡桃厨]而是我们所书写的[1,2,3]pytest.fixture(scopefunction,autouseFalse,paramsread_yaml()ids[1,2,3])def exe_database_sql(request):print(执行SQL查询)# 我们通过request.param获取数据可以采用yield返回该数据yield request.paramprint(关闭数据库连接)# nameFixture别名 # 作用是给fixtrue起别名一旦使用了别名那么fixtrue的名称就不能再用了只能用别名 class TestDemo:# 如果我们在这里使用到了别名pytest.fixture(scopefunction,nameexe_datebase_sql_name)def exe_database_sql(request):print(执行SQL查询)yield print(关闭数据库连接)# 我们这里就需要使用别名进行操作之前的名称无法使用def test_2(selfexe_datebase_sql_name):print(exe_database_sql) 接下来我们就将会讲解到我们刚刚提到的conftest.py文件 # 首先我们需要知道conftest.py文件的名字是固定形式不可改变 # conftest.py文件主要就是用来存储我们的Fixture然后我们会根据该文件的不同位置来判断可以使用的方法 # conftest可以在不同的目录级别下创建如果我们在根目录下创建那么所有case都会使用到该Fixture # 但是如果我们在testcases文件夹下的某个模块文件下创建conftest.py那么它的作用范围就只包含在该目录下# 根目录创建的conftest.py # 我们在该目录下的conftest文件里写的所有fixture可以在任意测试类下执行 import pytest pytest.fixture(scopefunction,nameexe_datebase_sql_name) def exe_database_sql():print(全部方法运行前均可以执行)yield print(全部方法运行后均可以执行) # testcases文件下的所有测试类 # 这里需要注意我们使用conftest下的Fixture时不需要import导包就可以使用 import pytest class TestDemo1:# 测试Case1def test_1(self,exe_datebase_sql_name):print(输入正确用户名密码验证码,点击登录 1 exe_datebase_sql_name)# testcases文件夹下的usercases文件夹下创建的conftest.py # 我们在该目录下创建的conftest文件里写的所有fixture仅可以在该目录下的测试类中使用在其他测试类中使用会出现报错 import pytest pytest.fixture(scopefunction,nameusercases_fixture) def exe_database_sql():print(usercases方法运行前均可以执行)yield print(usercases方法运行后均可以执行) # testcases文件下的usercases文件夹下的测试类 import pytest class TestUserCases1:# 测试Case1def test_1(self,usercases_fixture):print(输入正确用户名密码验证码,点击登录 1 usercases_fixture)# 最后我们简单给出一个前后置执行顺序优先级 fixture_session fixture_class setup_class fixture_function setup 然后最后我们给出前后置执行的一个总体逻辑顺序 查询当前目录下的conftest.py文件 查询当前目录下的pytest.ini文件并找到测试用例的位置 查询用例目录下的conftest.py文件 查询测试用例的py文件中是否有setup,teardown,setup_class,teardown_class 再根据pytest.ini文件的测试用例的规则去查找用例并执行 Pytest进阶内容 最后我们再来讲解一些pytest比较关键性的一些进阶内容 Allure效果美化 我们在使用Pytest所生成的页面往往不够美观且展示信息杂乱不好分析所以我们通常搭载allure来实现界面美化 Allure框架是一个灵活轻量级多语言测试报告工具 它不仅可以以WEB的方式展示简介的测试结果而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息 下面我们就来学习如何安装使用allure # 首先我们需要去下载在电脑上下载allure并配置好环境变量 # 我们这里给出官网下载地址https://github.com/allure-framework/allure2/releases # 温馨提醒下载链接在github上如果无法打开可以刷新重试或者使用加速器梯子等辅助工具 # 环境变量的配置只需要将bin文件所在目录放在电脑的Path路径下即可这里不再展示# 第二步我们需要在pycharm上下载allure-pytest插件如果之前pip了那个整体文件这里应该是已经下载过了 pip install allure-pytest# 第三步我们就可以直接来生成allure的测试结果展示界面了# 1.我们通常首先需要生成一个allure临时Json文件 # 我们通常会加上这么一串‐‐alluredir./temps ‐‐clean‐alluredir # ‐‐alluredir 文件生成地址 表示我们将allure临时文件生成在我们所指定的相对临时目录下 # ‐‐clean‐alluredir 由于每次都会生成大量文件所以我们会在生成前清除当前目录下的allure文件保证我们数据都是最新数据# 2.我们需要依靠临时文件来生成allure.html网页 # 我们通常在main方法中执行 if __name__ __main__:# 正常运行pytest.main()# 休眠主要为了JSON临时文件的生成time.sleep(3)# allure generate 固定语句 allure临时JSON文件目录 -o 输出指令 allure.html生成文件目录 --clean 清除旧数据os.system(allure generate ./temps ‐o ./reports ‐‐clean) Parametrize数据驱动 我们通常会采用Parametrize注解来进行数据驱动下面我们来详细讲解一下 # 格式pytest.mark.parametrize(参数名称参数值) # 意义我们会将参数名称作为id然后根据参数值的个数去依次调用存在n个参数值我们将会调用n次case# 1.参数值为列表或元组时参数名称可以为一个 # 首先我们这里因为使用单个元素的列表元组我们的参数名可以为一个 pytest.mark.parametrize(caseinfo,[胡桃,胡桃宝宝,芙芙芙芙宝宝]) # 在方法参数里我们需要调用parametrize的参数名称caseinfo需要保证一模一样 def test_01_get_token(self,caseinfo):# 在这里我们可以借助参数名称caseinfo来代替列表中的元素# 列表中存在几个我们该方法将执行几次例如现在列表是四个元素那么我们方法将会重复执行四次并每次按顺序赋值不同的元素print(获取统一接口鉴权码caseinfo)# 2.参数值为列表的多个时参数名称可以为多个 # 这里我们列表中嵌套了一个列表如果我们是单参数名称那么输出时就会将第一个列表[胡桃厨,胡桃宝宝]输出出去 # 但是如果我们是多参数名称系统会自动将第一个列表的元素分开赋值给arg1arg2便于我们分开使用个人还是比较推荐的 pytest.mark.parametrize(arg1,arg2,[[胡桃厨,胡桃宝宝],[芙芙厨,芙芙宝宝]]) # 注意这里当然也需要和参数名称对应 def test_01_get_token(self,arg1,arg2):print(获取统一接口鉴权码str(arg1) str(arg2)) 我们在进行数据驱动时通常会结合Yaml文件来进行数据获取这里我们简单介绍一下Yaml文件 # yaml是一种数据格式扩展名可以是yaml,yml # 支持#注释通过缩进表示层级区分大小写且yaml文件最后获取的结果展示是一个字典列表格式 # yaml文件经常用于书写配置例如Java的Spring中的配置文件而我们也经常采用yaml编写自动化测试用例# yaml文件通常会出现两种格式# 字典格式如果我们正常书写yaml文件如下就是字典模式 name: 胡桃# 列表模式如果我们采用yaml中的列表那么我们在py获取时也将获得列表 msjy:- name1: 胡桃- name2: 芙芙- ages1: 18- ages2: 19 # 我们也可以利用这个特性直接在yaml中做多个列表来多次提取 -name:xxxage:18 -name:xxxage:20# 我们这里首先给出一个解析yaml文件的示例函数 import os.path import yaml# 这里是获取当前路径因为我们需要找到对应的yaml文件那么具体路径就需要我们进行拼接 def get_obj_path():# 这里我们使用了Python的os类来进行当前路径获取最后返回结果其实是一个String字符串# 我们以common作为分界common是当前文件夹的名称我们将该Str进行划分获取前面的部分获取到前面的路径部分来进行拼接return os.path.dirname(__file__).split(common)[0]# 然后我们这里定义一个方法来解析yaml文件 def read_yaml(yamlPath):with open(get_obj_path() yamlPath,mode r,encoding utf-8) as f:# 这里需要我们pip install pyyamlvalue yaml.load(steamf,Loaderyaml.FullLoader)return value# 然后我们这里采用一个main方法来执行上述用例其实应该在其他测试类中执行 if __name__ __main__:# 调用read_yaml方法并给出yaml路径print(read_yaml(testcase/user_manage/get_token.yaml))# 了解了所有东西之前我们就可以结合之前的Parametrize来进行操作 # 我们这里将所需要的数据变为read_yaml读取的yaml文件内容 pytest.mark.parametrize(caseinfo,read_yaml(testcase/user_manage/get_token.yaml)) def test_01_get_token(self,caseinfo):# 这里我们就可以获取到yaml文件内容并输出了print(获取统一接口鉴权码caseinfo)# 当然如果我们了解我们的yaml中拥有什么元素我们还可以采用[]的方式具体表达出来 pytest.mark.parametrize(caseinfo,read_yaml(testcase/user_manage/get_token.yaml)) def test_01_get_token(self,caseinfo):print(获取统一接口鉴权码)# 这里我们可以直接获取namekey对应的valueprint(caseinfo[name] caseinfo[name])# 这里我们可以分别获取request层下的methodurldata分别对应的valueprint(caseinfo[name] caseinfo[request][method])print(caseinfo[name] caseinfo[request][url])print(caseinfo[name] caseinfo[request][data])
http://www.pierceye.com/news/273507/

相关文章:

  • 赣州做网站的公司有哪家好和县网站设计
  • 网站建设程序开发电销外呼软件
  • 金坛常州做网站成都分销商城网站建设
  • 网站商城系统建设厦门建站方案
  • 新郑郑州网站建设温州网站定制公司哪家好
  • 系统网站建设公司wordpress 命令行高亮
  • 怎样做招聘网站怎么在拼多多卖东西
  • 网站建设与网站管理网站怎么显示百度名片
  • 技术支持 盈岚网站建设典当行网站策划
  • 如何找到网站的模板页面中国优秀网站设计
  • 金融公司 网站开发简易个人博客网站源码
  • 小企业网站建设哪找网站制作软件dw
  • 百度收录提交网站后多久收录重庆个人房源网
  • 深圳网站建设制作公司排名网站设计怎么收费
  • 免费培训学校网站源码成免费crm破解版
  • w网站建设湖北建设厅举报网站
  • 营销型网站分为哪几种乐山网站建设公司
  • 淘宝网站建设类别好看的网站后台界面
  • 海口网站建设工作中企动力全球邮企业邮箱
  • 青岛网站制作排名绵阳做网站优化
  • 扬州市建设工程造价管理站网站开发建设网站
  • 广州网站设计公司济南兴田德润o评价潍坊响应式网站建设要多久
  • 网站模板如何优化平阳县建设局网站
  • 厦门外贸网站找谁可以做app的网站
  • 本地电脑静态网站建设游戏代理平台免费
  • 网站建设公司的成本有哪些内容wordpress admin空白
  • 高端网站建设如何收费济南行业网站建设
  • 昆明网站制作专业麦当劳订餐网站 是谁做的
  • 网站代备案公司名称网页游戏怎么搭建
  • 教师在哪些网站可以做兼职做平面的公司网站