Commit ff3eb667 authored by liangfenglong's avatar liangfenglong

123

parent 8f5f4f15

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

from __future__ import absolute_import, unicode_literals
import pymysql
# from .celery import app as celery_app
pymysql.install_as_MySQLdb()
__all__ = ['celery_app']
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from django.conf import settings
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'EasyTest.settings')
# 创建celery应用
app = Celery('EasyTest')
# Using a string here means the worker don't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
# 导入celery配置
app.config_from_object('django.conf:settings')
# Load task modules from all registered Django app configs.
# 自动注册celery任务
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
# 启动celery命令
# @app.task(bind=True)
# def debug_task(self):
# print('Request: {0!r}'.format(self.request))
"""
Django settings for EasyTest project.
Generated by 'django-admin startproject' using Django 2.0.
For more information on this file, see
https://docs.djangoproject.com/en/2.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.0/ref/settings/
"""
import os
from celery.schedules import crontab
from celery.schedules import timedelta
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '0y=3effs=f2e3wqz^sbqt(@d@&+*6*r^86(!p1f8n$ygumkk!i'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
ALLOWED_HOSTS = ['47.93.6.253', 'www.qalixy.com', 'localhost', '127.0.0.1']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'base',
'djcelery',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'EasyTest.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'EasyTest.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
"""
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
"""
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': "127.0.0.1",
'NAME': "uitest",
'USER': "root",
'PASSWORD': "qq88428977",
'PORT': "3306",
}
}
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.mysql',
# 'HOST': "127.0.0.1",
# 'NAME': "uitest",
# 'USER': "root",
# 'PASSWORD': "qwe123",
# 'PORT': "3306",
# 'OPTIONS':{
# "init_command":"SET foreign_key_checks = 0;", }
# }
# }
# Password validation
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
# 页面展示时间比数据库时间快8h
# USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
# session 设置
SESSION_COOKIE_AGE = 60 * 60 # 30分钟
SESSION_SAVE_EVERY_REQUEST = True
SESSION_EXPIRE_AT_BROWSER_CLOSE = True # 关闭浏览器,则COOKIE失效
# 上传
MEDIA_ROOT = 'media' # 对应文件夹
MEDIA_URL = '/media/' # 对应上线后的url
STATIC_URL = '/static/'
STATIC_ROOT = '/var/static/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
os.path.join(BASE_DIR,'templates','report')
]
# 配置缓存
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/2",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"PICKLE_VERSION": -1,
}
}
}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
# 自定义配置
REDIS = {
'host': 'localhost',
'port': '6379',
# 'password': 123456,
'db': '2',
}
# log
# 导入模块
import time
cur_path = os.path.dirname(os.path.realpath(__file__)) # log_path是存放日志的路径
log_path = os.path.join(os.path.dirname(cur_path), 'logs')
if not os.path.exists(log_path): os.mkdir(log_path) # 如果不存在这个logs文件夹,就自动创建一个
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
# 日志格式
'standard': {
'format': '[%(asctime)s] [%(filename)s:%(lineno)d] [%(module)s:%(funcName)s] '
'[%(levelname)s]- %(message)s'},
'simple': { # 简单格式
'format': '%(levelname)s %(message)s'
},
},
# 过滤
'filters': {
},
# 定义具体处理日志的方式
'handlers': {
# 默认记录所有日志
'default': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(log_path, 'all-{}.log'.format(time.strftime('%Y-%m-%d'))),
'maxBytes': 1024 * 1024 * 5, # 文件大小
'backupCount': 5, # 备份数
'formatter': 'standard', # 输出格式
'encoding': 'utf-8', # 设置默认编码
},
# 输出错误日志
'error': {
'level': 'ERROR',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(log_path, 'error-{}.log'.format(time.strftime('%Y-%m-%d'))),
'maxBytes': 1024 * 1024 * 5, # 文件大小
'backupCount': 5, # 备份数
'formatter': 'standard', # 输出格式
'encoding': 'utf-8', # 设置默认编码
},
# 控制台输出
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'standard'
},
# 输出info日志
'info': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(log_path, 'info-{}.log'.format(time.strftime('%Y-%m-%d'))),
'maxBytes': 1024 * 1024 * 5,
'backupCount': 5,
'formatter': 'standard',
'encoding': 'utf-8', # 设置默认编码
},
},
# 配置用哪几种 handlers 来处理日志
'loggers': {
# 类型 为 django 处理所有类型的日志, 默认调用
'django': {
'handlers': ['default', 'console'],
'level': 'INFO',
'propagate': False
},
# log 调用时需要当作参数传入
'log': {
'handlers': ['error', 'info', 'console', 'default'],
'level': 'INFO',
'propagate': True
},
}
}
import djcelery
djcelery.setup_loader()
# celery中间人 redis://redis服务所在的ip地址:端口/数据库号
BROKER_URL = 'redis://127.0.0.1:6379/'
CELERY_IMPORTS = ('base.tasks')
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'
CELERYBEAT_SCHEDULE = { # 定时器策略
# 定时任务一: 每隔30s运行一次
# u'测试定时器1': {
# "task": "base.tasks.hello_world",
# # "schedule": crontab(minute='*/2'), # or 'schedule': timedelta(seconds=3),
# "schedule": timedelta(seconds=30),
# "args": (),
# },
}
"""
Django settings for EasyTest project.
Generated by 'django-admin startproject' using Django 2.0.
For more information on this file, see
https://docs.djangoproject.com/en/2.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.0/ref/settings/
"""
import os
from celery.schedules import crontab
from celery.schedules import timedelta
from redis import StrictRedis
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '0y=3effs=f2e3wqz^sbqt(@d@&+*6*r^86(!p1f8n$ygumkk!i'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*', '129.28.187.64', '127.0.0.1']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'base',
'djcelery',
'stress',
'dwebsocket',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
MIDDLEWARE_CLASSES = [
"dwebsocket.decorators.WebSocketMiddleware",
]
WEBSOCKET_ACCEPT_ALL = True
ROOT_URLCONF = 'EasyTest.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'EasyTest.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
"""
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
"""
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': "127.0.0.1",
'NAME': "easytest",
'USER': "root",
'PASSWORD': "gengmei123",
'PORT': "3306",
}
}
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.mysql',
# 'HOST': "127.0.0.1",
# 'NAME': "uitest",
# 'USER': "root",
# 'PASSWORD': "qwe123",
# 'PORT': "3306",
# 'OPTIONS':{
# "init_command":"SET foreign_key_checks = 0;", }
# }
# }
# Password validation
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
# 页面展示时间比数据库时间快8h
# USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
# session 设置
SESSION_COOKIE_AGE = 60 * 60 # 30分钟
SESSION_SAVE_EVERY_REQUEST = True
SESSION_EXPIRE_AT_BROWSER_CLOSE = True # 关闭浏览器,则COOKIE失效
# 上传
MEDIA_ROOT = 'media' # 对应文件夹
MEDIA_URL = '/media/' # 对应上线后的url
STRESS_ROOT = os.path.join(BASE_DIR, 'templates', 'report') # 对应文件夹
STRESS_URL = '/report/' # 对应上线后的url
STATIC_URL = '/static/'
STATIC_ROOT = '/var/static/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
os.path.join(BASE_DIR, 'templates', 'report')
]
# 配置缓存
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/2",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"PICKLE_VERSION": -1,
}
}
}
# 自定义配置
REDIS = {
'host': 'localhost',
'port': '6379',
# 'password': 123456,
'db': '2',
}
# log
# 导入模块
import time
cur_path = os.path.dirname(os.path.realpath(__file__)) # log_path是存放日志的路径
log_path = os.path.join(os.path.dirname(cur_path), 'logs')
if not os.path.exists(log_path): os.mkdir(log_path) # 如果不存在这个logs文件夹,就自动创建一个
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
# 日志格式
'standard': {
'format': '[%(asctime)s] [%(filename)s:%(lineno)d] [%(module)s:%(funcName)s] '
'[%(levelname)s]- %(message)s'},
'simple': { # 简单格式
'format': '%(levelname)s %(message)s'
},
},
# 过滤
'filters': {
},
# 定义具体处理日志的方式
'handlers': {
# 默认记录所有日志
'default': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(log_path, 'all-{}.log'.format(time.strftime('%Y-%m-%d'))),
'maxBytes': 1024 * 1024 * 5, # 文件大小
'backupCount': 5, # 备份数
'formatter': 'standard', # 输出格式
'encoding': 'utf-8', # 设置默认编码
},
# 输出错误日志
'error': {
'level': 'ERROR',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(log_path, 'error-{}.log'.format(time.strftime('%Y-%m-%d'))),
'maxBytes': 1024 * 1024 * 5, # 文件大小
'backupCount': 5, # 备份数
'formatter': 'standard', # 输出格式
'encoding': 'utf-8', # 设置默认编码
},
# 控制台输出
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'standard'
},
# 输出info日志
'info': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(log_path, 'info-{}.log'.format(time.strftime('%Y-%m-%d'))),
'maxBytes': 1024 * 1024 * 5,
'backupCount': 5,
'formatter': 'standard',
'encoding': 'utf-8', # 设置默认编码
},
},
# 配置用哪几种 handlers 来处理日志
'loggers': {
# 类型 为 django 处理所有类型的日志, 默认调用
'django': {
'handlers': ['default', 'console'],
'level': 'INFO',
'propagate': False
},
# log 调用时需要当作参数传入
'log': {
'handlers': ['error', 'info', 'console', 'default'],
'level': 'INFO',
'propagate': True
},
}
}
import djcelery
djcelery.setup_loader()
# celery中间人 redis://redis服务所在的ip地址:端口/数据库号
BROKER_URL = 'redis://127.0.0.1:6379/'
CELERY_IMPORTS = ('base.tasks')
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'
CELERYBEAT_SCHEDULE = { # 定时器策略
# 定时任务一: 每隔30s运行一次
# u'测试定时器1': {
# "task": "base.tasks.hello_world",
# # "schedule": crontab(minute='*/2'), # or 'schedule': timedelta(seconds=3),
# "schedule": timedelta(seconds=30),
# "args": (),
# },
}
LOGIN_URL = '/login_action/'
GM_LOGIN_URI = '/api/accounts/login/password'
# 搞一个redis实例
GM_REDIS = StrictRedis()
JMX_ROOT = '/tmp'
JMX_PATHS = ['jmeter_jmx', 'jmeter_live', 'jmeter_service']
"""EasyTest URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
# from django.urls import path
from django.conf.urls import include
# from EasyTest.views import index
from EasyTest import views
from django.conf import settings
from django.conf.urls import url
from django.conf.urls.static import static
from django.views.generic.base import RedirectView
urlpatterns = [
url(r'admin/', admin.site.urls),
url(r'^login_action/', view=views.login_action, name='login_action'),
url(r'^logout/', view=views.logout, name='logout'), # 退出
url(r'^img_download/', view=views.img_download, name='img_download'), # 下载图片
url(r'^base/', include("base.urls"), name='base'),
url(r'^press/', include("stress.urls"), name='press'),
url(r'^favicon.ico$', RedirectView.as_view(url=r'/static/img/favicon.png')),
url(r'index/', view=views.index, name='index'),
url(r'^$', view=views.index),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STRESS_URL, document_root=settings.STRESS_ROOT)
handler400 = views.bad_request
handler403 = views.permission_denied
handler404 = views.page_not_found
handler500 = views.server_error
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect, JsonResponse, HttpResponse
from django.contrib import auth # django认证系统
from djcelery.models import PeriodicTask, CrontabSchedule
from django.contrib.auth.models import User
from django.db.models import Count
from base.models import Project, Environment, Interface, Case, Plan, Report
import logging, os
from django.http import StreamingHttpResponse
from lib.public import gr_code
from lib.execute import get_user
from django.contrib.auth import authenticate, login
log = logging.getLogger('log') # 初始化log
from base.models import User
from django.conf import settings
num_list = []
@login_required(login_url=settings.LOGIN_URL)
def index(request):
if request.method == 'POST':
user_id = request.session.get('user_id', '') # 从session中获取user_id
if get_user(user_id):
url = request.POST.get('url', '')
if url:
qr_code_name = gr_code(url)
log.info('用户 {} 生成二维码 {}-->{}'.format(user_id, qr_code_name, url))
return JsonResponse(str(qr_code_name), safe=False)
else:
return HttpResponse('0')
else:
project_num = Project.objects.aggregate(Count('prj_id'))['prj_id__count']
env_num = Environment.objects.aggregate(Count('env_id'))['env_id__count']
interface_num = Interface.objects.aggregate(Count('if_id'))['if_id__count']
case_num = Case.objects.aggregate(Count('case_id'))['case_id__count']
plan_num = Plan.objects.aggregate(Count('plan_id'))['plan_id__count']
# sign_num = Sign.objects.aggregate(Count('sign_id'))['sign_id__count']
report_num = Report.objects.aggregate(Count('report_id'))['report_id__count']
periodic_num = PeriodicTask.objects.aggregate(Count('id'))['id__count']
crontabSchedule_num = CrontabSchedule.objects.aggregate(Count('id'))['id__count']
username = request.session.get('user', '')
num_list = [project_num, env_num, interface_num, case_num, plan_num, report_num,
periodic_num + crontabSchedule_num]
return render(request, "index.html",
{'username': username, 'num_list': num_list, 'project_num': project_num,
'env_num': env_num, 'interface_num': interface_num, 'case_num': case_num,
'plan_num': plan_num, 'report_num': report_num,
'task_num': periodic_num + crontabSchedule_num})
# 登录
next = '/'
def login_action(request):
global next
if request.method.upper() == 'GET':
next = request.GET.get('next') or next
if request.user.is_authenticated:
return redirect(next)
return render(request, 'user/login_action.html')
# print('*'*100)
# print(request.__dict__)
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user:
login(request, user)
request.session['uid'] = User.objects.get(username = username).id
render_data = redirect(next)
return render_data
return render(request, 'user/login_action.html', context={'error': '用户名或密码错误!'})
# @login_required
def img_download(request):
# do something...
user_id = request.session.get('user_id', '') # 从session中获取user_id
if get_user(user_id):
if request.method == 'GET':
name = request.GET.get('log_file', '')
name_path = os.path.join('/home/ubuntu/EasyTest/media', name)
def file_iterator(file_name, chunk_size=512):
with open(file_name, 'rb') as f:
while True:
c = f.read(chunk_size)
if c:
yield c
else:
break
response = StreamingHttpResponse(file_iterator(name_path))
response['Content-Type'] = 'application/octet-stream'
response['Content-Disposition'] = 'attachment;filename="{0}"'.format(name_path)
log.info('用户 {} 下载的二维码:{}'.format(user_id, name_path))
return response
else:
request.session['login_from'] = '/index/'
return render(request, 'user/login_action.html')
# 退出
def logout(request):
username = request.session.get('user', '')
log.info('用户:{},退出登录!'.format(username))
auth.logout(request) # 退出登录
response = HttpResponseRedirect(settings.LOGIN_URL)
return response
# 400
def bad_request(request, exception, template_name='error_page/400.html'):
log.error('-------------------->400 error<--------------------')
return render(request, template_name)
# 403
def permission_denied(request, exception, template_name='error_page/403.html'):
log.error('-------------------->403 error<--------------------')
return render(request, template_name)
# 404
def page_not_found(request, exception, template_name='error_page/404.html'):
log.error('-------------------->404 error<--------------------')
return render(request, template_name)
# 500
def server_error(exception, template_name='error_page/500.html'):
log.error('-------------------->500 error<--------------------')
return render(exception, template_name)
"""
WSGI config for EasyTest project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
# os.environ.setdefault("DJANGO_SETTINGS_MODULE", "EasyTest.settings")
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'EasyTest.pro_settings') # 部署环境
application = get_wsgi_application()
<<<<<<< HEAD
## 接口自动化测试平台
##### 需要先配置redis并启动 redis-server
redis命令参考 停止 redis-cli shutdown
- 项目管理
- 测试环境(header项,目前为必填)
- web参考 ({'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'})
- app参考({'User-Agent': 'Gengmei/7.10.0 (iPhone; iOS 12.1.4; Scale/3.00)'})
- 单接口管理
- 用例管理
- 测试任务
- 定时任务(需要启动celery, celery -A _celery worker -l info)
- 运行报告
- 性能报告(需要 在 Terminal 中 手动执行 locust -f /Users/xxx存储地址/base/performance.py)
- 签名 (目前仅支持md5)
#### 待解决问题:
- 测试用例的取值问题
- 全局变量 引用功能
账号:qalixy 密码:123456
ps:
样式模板
http://www.templatesy.com/Article/674.html
=======
# EasyTest
>>>>>>> 8f5f4f15760e49f7284679b769e06d53e93fcb31
# !/usr/bin/env python
# coding=utf-8
from multiprocessing import cpu_count
bind = '127.0.0.1:9000'
daemon = True # 守护进程
workers = cpu_count() * 2
worker_class = 'gevent'
forwarded_allow_ips = '*'
# 维持TCP链接
keepalive = 6
timeout = 65
graceful_timeout = 10
worker_connections = 65535
# log
capture_output = True
loglevel = 'info'
accesslog = "/var/logs/EasyTest_access.log" #访问日志文件的路径
errorlog = "/var/logs/EasyTest_error.log"
/Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m
\ No newline at end of file
/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/include/python3.7m
\ No newline at end of file
This diff is collapsed.
#!/usr/bin/env python
# encoding: utf-8
'''
# 创 建 人: 李木子
# 文 件 名: __init__.py
# 说 明:
# 创建时间: 2019/6/23
'''
#!/usr/bin/python
# -*- coding: utf-8 -*-
import requests
import json
import sys
import os
import urllib3
urllib3.disable_warnings()
headers = {'Content-Type': 'application/json;charset=utf-8'}
api_url = "https://oapi.dingtalk.com/robot/send?access_token=3b001da911089ffc4b4eeb588ef80dae2afeb778468fe2acb5099552dd78fee5"
def msg(text, develop):
from base.models import Development
tel = Development.objects.get(name=develop).tel
print(tel)
json_text = {
"msgtype": "text",
"at": {
"atMobiles": [
tel
],
"isAtAll": False
},
"text": {
"content": text
}
}
print(requests.post(api_url, json.dumps(json_text), headers=headers, verify=False).content)
# if __name__ == '__main__':
# text = "测试"
# msg(text)
\ No newline at end of file
This diff is collapsed.
upstream EasyTest_master {
# 此处为uwsgi运行的ip地址和端口号
server 172.17.248.213:8000;
# server 127.0.0.1:9100;
}
server {
# 监听端口 ,域名端口
listen 80;
# 服务器域名或者ip地址
server_name 47.93.6.253 .qalixy.com;
# 编码
charset utf-8;
# 文件最大上传大小
client_max_body_size 75M;
# 媒体文件
location /media {
alias /home/lixy/AutoTestPram/EasyTest_master/media;
}
# 静态文件
location /static {
alias /home/lixy/AutoTestPram/EasyTest_master/static;
}
# 主目录 uwsgi_pass反向代理
location / {
uwsgi_pass EasyTest_master;
include /etc/nginx/uwsgi_params;
}
# location / {
# proxy_pass http://localhost:9100;
# }
}
\ No newline at end of file
import json
import os, logging
# from common.connectDB import SqL
from jsonpath_rw import jsonpath, parse
log = logging.getLogger('log') # 初始化log
# sql = SqL()
# windows
sql_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + '\\data' + '\\data.json' # params json file
res_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + '\\data' + '\\res.json' # headers json file
rely_on_path = os.path.abspath(
os.path.dirname(os.path.dirname(__file__))) + '\\data' + '\\rely_on.json' # 临时文件,存接口返回的参数
# linux
# json_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + '/data' + '/data.json'
def get_json(path, field=''):
"""获取json文件中的值,data.json和res.json可共用"""
with open(path, 'r', encoding='utf-8') as f:
json_data = json.load(f)
if field:
data = json_data.get(field)
return data
else:
return json_data
def analysis_json(res, filed):
"""解析请求返回的json数据,返回依赖的字段和值组成的字典"""
if isinstance(res, dict):
if filed:
jsonpath_expr = parse(filed)
male = jsonpath_expr.find(res)
value_list = [match.value for match in male]
for value in value_list:
data_dict = {filed: value}
return data_dict
else:
log.error('{}传入字段异常!'.format(analysis_json.__name__))
else:
log.error('{} 参数不是字典类型'.format(analysis_json.__name__))
def write_body(res, field):
"""请求返回值写入data.json中,在body参数中使用。data.json中要提前写入需要的字段,然后用从返回值中提取的结果替换"""
if isinstance(res, dict):
if field:
with open(sql_path, 'r', encoding='utf-8') as f:
json_data = json.load(f)
for key in json_data:
if isinstance(json_data[key], dict):
for k in json_data[key]:
if k == field:
json_data[key][field] = res[field]
with open(sql_path, 'w', encoding='utf-8') as fp:
fp.write(str(json_data).replace("'", '"'))
log.info('请求返回值写入json成功!field ==> {}'.format(field))
else:
log.error('{}传入字段异常!'.format(analysis_json.__name__))
else:
log.error('{} 参数不是字典类型'.format(write_body.__name__))
def write_data(res, json_path):
"""把处理后的参数写入json文件"""
if isinstance(res, dict):
with open(json_path, 'w', encoding='utf-8') as f:
json.dump(res, f, indent=4)
log.info('Interface Params Total:{} ,write to json file successfully!\n'.format(len(res)))
else:
log.info('{} Params is not dict.\n'.format(write_data.__name__))
if __name__ == '__main__':
# body = get_json(json_path, 'registered_member')
# print(body)
# for k, v in body.items():
# print(k,v)
# data = {'uid': 99, 'ukey': 'bef0246cb2059d90c5e4af8accdf4429'}
# write_headers(data)
data = get_json(res_path)
print(data)
This diff is collapsed.
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/__future__.py
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment