ファンド管理会社がオフラインで面接の質問をテスト
公開アカウント: Meng Wiji のテスト開発への道
試験問題は以下の通りです
最初に自分で書いてみて、完成後にリファレンスソリューションを見ることができます~
1. リスト内の数値を 2 乗するコードを作成します (言語の制限はありません)。
リストA = [1、3、5、7、9、11]
2. Python 言語を使用してログ デコレータを作成する
3. プロセス、スレッド、コルーチンの違いは何ですか?
4. Seleniumフレームワークの動作原理を描いてください(Appiumでも可)
5. 自動テスト プロジェクトの主要なノードは何ですか? 例を挙げてください。
6. Django フレームワークのリクエスト処理 (つまり、リクエストのライフサイクル) を描画してください。関数呼び出しリンクが何であるかを記述できれば (Django を使用したことがない場合は、使用したフレームワークを描画できます)
7. wsgiref の機能は何ですか?
8. Django にはどのようなミドルウェアがありますか? ミドルウェアの 5 つのメソッドと適用シナリオを挙げてください。
9. WSGl/uwsgi/uwSGI の 3 つの概念の違いを簡単に説明してください? uWSGI があるのに、なぜ nginx が必要なのでしょうか?
10. MySQL ストレージ エンジンをいくつか挙げてください。それぞれの長所と短所は何ですか?
11. Docker C/S アーキテクチャ図を描いてください
12. dockerコマンドを使用して操作してください
a) kumaという名前のボリュームを作成します
b) yapi という名前のコンテナを起動し、バックグラウンドで実行し、ホストの 5000 ポートをコンテナ内の 3000 ポートにマップし、上で作成したボリュームを使用して /data/db ディレクトリにマウントします。
問題解決の参考資料は以下の通りです
1. リスト内の数値を 2 乗するコードを作成します (言語の制限はありません)。
入力: ListA = [1、3、5、7、9、11]
出力: [1、9、25、49、81、121]
Javaコード:
// 方法一
import java.util.ArrayList;
import java.util.List;
public class SquareList {
public static void main(String[] args) {
List<Integer> listA = new ArrayList<Integer>();
listA.add(1);
listA.add(3);
listA.add(5);
listA.add(7);
listA.add(9);
listA.add(11);
List<Integer> squaredList = new ArrayList<Integer>();
for (int num : listA) {
squaredList.add(num * num);
}
System.out.println(squaredList);
}
}
// 方法二
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class SquareList {
public static void main(String[] args) {
List<Integer> listA = Arrays.asList(1, 3, 5, 7, 9, 11);
List<Integer> squaredList = listA.stream()
.map(num -> num * num)
.collect(Collectors.toList());
System.out.println(squaredList);
}
}
Java 8 で導入された Stream API を使用すると、よりクリーンなコードを実現できます。上記のコードでは、listA
ストリームに変換し、次にmap()
演算を使用して各要素を 2 乗し、最後にcollect()
演算を使用して結果を新しいリストに収集します。このようにして、二乗リストを取得し、結果を出力します。
ゴーコード
package main
import (
"fmt"
)
func main() {
listA := []int{
1, 3, 5, 7, 9, 11}
squaredList := make([]int, len(listA))
for i, num := range listA {
squaredList[i] = num * num
}
fmt.Println(squaredList)
}
Pythonコード
# 方法一,使用列表推导式
listA = [1, 3, 5, 7, 9, 11]
squared_list = [num**2 for num in listA]
print(squared_list) # [1, 9, 25, 49, 81, 121]
# 方法二,使用map方法
listA = [1, 3, 5, 7, 9, 11]
squared_list = list(map(lambda num: num**2, listA))
print(squared_list)
map()
Function は関数と反復可能を引数として受け取り、その関数を反復可能内の各要素に適用します。
#方法三,普通for循环(这应该不是面试官想看到的,但却是最好理解的)
listA = [1, 3, 5, 7, 9, 11]
squared_list = []
for i in listA:
squared_list.append(i*i) # 写成 i**2 也是可以的
print(squared_list)
**2
数値の二乗を表します。
2. Python 言語を使用してログ デコレータを作成する
方法 1: 簡易バージョン
def log_decorator(func):
def wrapper(*args, **kwargs):
print("调用函数:", func.__name__)
print("传入的参数:", args, kwargs)
result = func(*args, **kwargs)
print("函数返回结果:", result)
return result
return wrapper
@log_decorator
def add(a, b):
return a + b
result = add(3, 5)
print("最终结果:", result) # 最终结果: 8
方法 1: もう少しシンプルなバージョン
import logging
logging.basicConfig(level=logging.INFO)
def log_decorator(func):
def wrapper(*args, **kwargs):
logger = logging.getLogger()
logger.info("调用函数: %s", func.__name__)
logger.info("传入的参数: %s %s", args, kwargs)
result = func(*args, **kwargs)
logger.info("函数返回结果: %s", result)
return result
return wrapper
@log_decorator
def add(a, b):
return a + b
result = add(3, 5)
print("最终结果:", result)
コードではあまり説明がありません。
ログにはさらに多くの形式を追加できます。以前の記事のログ部分への参照は次のとおりです: Python コマンド ライン、コンソール、または色付きのログ出力 (qq.com)
3. プロセス、スレッド、コルーチンの違いは何ですか?
プロセス、スレッド、コルーチンは、コンピューターで同時実行性と並列性を実装するために使用される概念であり、それぞれの違いは次のとおりです。
-
プロセス:
- プロセスは、オペレーティング システムによるリソースの割り当てとスケジューリングの基本単位です。
- 各プロセスは独自の独立したアドレス空間、スタック、データセグメントを持ち、相互にメモリを共有しません。
- プロセス間の通信には、パイプ、シグナル、メッセージ キューなどのプロセス間通信 (IPC) メカニズムが必要です。
- プロセス間の切り替えにはコストがかかり、多くのリソースを消費します。
- プロセスは互いに独立しており、クラッシュや例外が他のプロセスに影響を与えることはありません。
-
スレッド (スレッド):
- スレッドは、プロセス内で実行される独立した実行ストリームです。
- 同じプロセス内のスレッドは、メモリ、ファイル ハンドルなどのリソースを共有します。
- スレッド間の切り替えのオーバーヘッドは比較的小さく、消費するリソースも少なくなります。
- スレッドは共有メモリを介して通信しますが、スレッドの同期と相互排他の問題に注意する必要があります。
- スレッドのクラッシュまたは例外により、プロセス全体がクラッシュする可能性があります。
-
コルーチン:
- コルーチンはユーザー モードの軽量スレッドであり、マイクロスレッドとも呼ばれます。
- コルーチンのスケジューリングはプログラマ自身によって制御され、コンテキストは、yield/yield from などのキーワードを使用して実行中に保存および復元できます。
- コルーチン間の切り替えコストは非常に小さく、非同期操作を効率的に実行してプログラムの同時実行パフォーマンスを向上させることができます。
- コルーチンは、IO 集中型のタスクの処理には適していますが、コンピューティング集中型のタスクの場合は、マルチスレッドまたはマルチプロセスで使用する必要があります。
プロセスの使用にはどのようなシナリオが適していますか?
計算負荷の高いタスク (大規模なデータの計算や処理など)
スレッドの使用に適しているのはどのようなシナリオですか?
IO 集中型のタスク (例: ファイルの読み取りと書き込みが多いタスク、ネットワーク リクエストが多いタスク)
コルーチンの使用にはどのようなシナリオが適していますか?
IO 集約型のプロジェクトでは、高い同時実行性が必要です (たとえば、locust を使用したストレス テストではコルーチンが使用されます) 実際のプロジェクトでは、同時実行性の高い企業は Python 言語の使用を選択しません。
要約すると、プロセスはオペレーティング システムにおけるリソース割り当てとスケジューリングの基本単位であり、スレッドはプロセス内で実行される独立した実行ストリームであり、コルーチンはユーザー モードの軽量スレッドです。リソース占有量、スイッチングオーバーヘッド、通信方式などが異なりますので、状況に応じて適切な同時実行方式を選択する必要があります。
後で、特にプロセス スレッド コルーチンについていくつかの記事を書く予定です。
4. Seleniumフレームワークの動作原理を描いてください(Appiumでも可)
セレンの仕組み
- Selenium クライアント (Python およびその他の言語で記述された自動テスト スクリプト) は、サービス サービスを初期化し、Webdriver を通じてブラウザ ドライバー chromedriver.exe を開始します。
- RemoteWebDriver を介してブラウザ ドライバに HTTP リクエストを送信します。ブラウザ ドライバはリクエストを解析し、ブラウザを開き、セッション ID を取得します。ブラウザを再度操作する場合は、この ID を保持する必要があります。
- ブラウザを開き、特定のポートをバインドし、起動したブラウザを Webdriver のリモート サーバーとして使用します。
- ブラウザを開いた後、すべての Selenium 操作 (アクセス アドレス、検索要素など) は RemoteConnection を通じてリモート サーバーにリンクされ、execute メソッドを使用して _request メソッドを呼び出し、urlib3 を通じてリモート サーバーにリクエストを送信します。
- ブラウザは、要求されたコンテンツに基づいて対応するアクションを実行します。
- 次に、ブラウザは実行されたアクションの結果をブラウザ ドライバを通じてテスト スクリプトに返します。
Appium の仕組み
5. 自動テスト プロジェクトの主要なノードは何ですか? 例を挙げてください。
この質問は非常に広範囲であり、考慮する必要がある要素がたくさんあります。履歴書や職歴に基づいて詳しく説明できます。参考となる重要なポイントは次のとおりです。
1. 機能テスト ケースから自動テスト ケースをフィルタリングする
2. 実行可能な自動テストケースに関する調査と実践のディスカッション
3. 関連する自動化ソリューションのスケジュール、期待、見通し
3. 自動テスト フレームワークを選択するか、対応する自動テスト フレームワークを自分で構築します
4. 自動スクリプト作成
5. 継続的インテグレーションと自動構築
6. 定期的なメンテナンスとアップデート
7. 自動化の実装 (最も重要)
6. Django フレームワークのリクエスト処理 (つまり、リクエストのライフサイクル) を描画してください。関数呼び出しリンクが何であるかを記述できれば (Django を使用したことがない場合は、使用したフレームワークを描画できます)
- ユーザーはブラウザ経由でリクエストを送信します
- リクエストはリクエスト ミドルウェアに到達し、ミドルウェアはリクエストを前処理するか、応答を直接返します。
- 応答が返されない場合は、urlconf ルートに到達し、対応するビュー関数が見つかります。
- view 関数は、対応する前処理を実行するか、応答を直接返します。
- ビュー内のメソッドは、モデルを通じて基になるデータに選択的にアクセスできます
- 対応するデータを取得した後、Django テンプレート システムに戻り、テンプレートはフィルターまたはタグを通じてデータをテンプレートにレンダリングします。
- 応答をブラウザに返し、クライアントに表示します。
7. wsgiref の機能は何ですか?
wsgiref は、WSGI (Web Server Gateway Interface) サーバーとミドルウェアのシンプルかつ効果的な実装を提供する Python 標準ライブラリのモジュールです。これは主に、simple_server、util、headers、handlers、validate の 5 つのモジュールに分かれています。
wsgiref ソースコードのアドレス: https://pypi.python.org/pypi/wsgiref
8. Django にはどのようなミドルウェアがありますか? ミドルウェアの 5 つのメソッドと適用シナリオを挙げてください。
Django は、リクエストとレスポンスを処理するための組み込みミドルウェアを多数提供します。以下は、一般的に使用される 5 つのミドルウェアとそのアプリケーション シナリオです。
-
SessionMiddleware
: セッション状態を扱うミドルウェア。リクエスト処理中にセッション オブジェクトを追加することで、セッション管理をサポートします。アプリケーション シナリオには、ユーザー認証およびユーザー ステータス追跡機能が含まれます。 -
AuthenticationMiddleware
: ユーザー認証を行うミドルウェア。各リクエスト処理中にユーザーの認証ステータスをチェックし、ユーザーの認証情報をリクエスト オブジェクトに追加する役割を果たします。アプリケーション シナリオには、ユーザー ログイン、権限制御、認証が含まれます。 -
CsrfViewMiddleware
: クロスサイト リクエスト フォージェリ (CSRF) 保護を処理するミドルウェア。POST リクエストごとに CSRF トークンが自動的に生成され、フォームの送信時にトークンの有効性が検証されます。アプリケーション シナリオには、フォーム送信を CSRF 攻撃から保護することが含まれます。 -
GZipMiddleware
: 圧縮された応答を処理するためのミドルウェア。応答を送信する前にコンテンツを GZip 圧縮するため、データ転送のサイズが削減されます。アプリケーション シナリオには、Web サイトのパフォーマンスの向上と帯域幅消費の削減が含まれます。 -
LocaleMiddleware
: 多言語対応ミドルウェア。これは、リクエストで提供された言語設定に基づいて適切なロケールを設定し、それをリクエストの応答に適用することによって行われます。アプリケーション シナリオには、多言語 Web サイトや国際化されたアプリケーションが含まれます。
これらのミドルウェアは、Django アプリケーションに簡単に統合できる、一般的に使用される一連の関数とハンドラーを提供し、開発者の作業を簡素化します。特定のニーズに応じて、これらのミドルウェアを必要に応じて有効にして構成し、さまざまな機能と処理ロジックを実装できます。
9. WSGl/uwsgi/uwSGI の 3 つの概念の違いを簡単に説明してください? uWSGI があるのに、なぜ nginx が必要なのでしょうか?
WSGI
WSGI (Web サーバー ゲートウェイ インターフェイス): WSGI は、Python Web アプリケーションとサーバーの間で広く受け入れられ、使用されている標準インターフェイスです。これは、Web サーバーと Web アプリケーション間の通信ルールを定義し、サーバーがアプリケーションを理解して対話できるようにします。WSGI 仕様により、開発者は特定のサーバーの詳細を気にすることなく、統一された方法を使用して Web アプリケーションを作成できます。
つまり、 Web サーバー (nginx、uWSGI、その他のサーバーなど) が Web アプリケーション (Django や Flask フレームワークで書かれたプログラムなど) と通信する方法を記述するプロトコルです。
uwsgiプロトコル
これは、uWSGI サーバー独自のプロトコルであり、通信プロトコルではなく回線プロトコルです。これは、送信される情報の種類を定義するために使用されます。各 uwsgi パケットの最初の 4 バイトは、送信される情報の種類の説明です。nginx などのプロキシ サーバーとの通信に使用されます。WSGI とは 2 つの異なるものです。
uwSGI
これは、uwsgi と WSGI という 2 つのプロトコルを実装するWeb サーバーです。
uWSGI があるのに、なぜ nginx が必要なのでしょうか?
これは、Nginx と uWSGI の役割が異なるためです。Nginx は主にフロントエンド サーバー、リバース プロキシ、ロード バランサーとして機能し、静的リソースと多数の同時接続を処理し、バックエンドの uWSGI プロセスにリクエストを転送して動的リクエストを処理できます。uWSGI は Web アプリケーションからのリクエストの処理に重点を置いており、WSGI プロトコルをサポートし、アプリケーション コードの解析と実行を担当します。したがって、Nginx と uWSGI を組み合わせることで、システムのパフォーマンス、信頼性、セキュリティが向上し、より優れた負荷分散とより高い同時処理能力を実現できます。
10. MySQL ストレージ エンジンをいくつか挙げてください。それぞれの長所と短所は何ですか?
MySQL はさまざまなストレージ エンジンを提供しており、それぞれに独自の機能と適用可能なシナリオがあります。一般的な MySQL ストレージ エンジンとその長所と短所をいくつか示します。
-
InnoDB:
- 利点: トランザクション処理と外部キー制約をサポートし、高い同時実行パフォーマンスとデータ整合性を提供します。行レベルのロックとマルチバージョン同時実行制御 (MVCC) のサポートがあり、大量の同時書き込みや多数の読み取りと書き込みが混在するシナリオに適しています。
- 欠点: 他のストレージ エンジンと比較して、InnoDB のストレージ速度と読み取り速度は比較的遅いです。トランザクションと ACID 機能をサポートしているため、より多くのディスク容量が必要です。
-
マイサム:
- 利点: 読み取りパフォーマンスが高く、多数の読み取り専用操作や全文検索に適しています。データの保存とインデックス作成は非常にコンパクトで、必要なディスク容量も少なくなります。
- 欠点: トランザクションと外部キー制約はサポートされていません。行レベルのロックはなく、テーブル レベルのロックのみをサポートするため、同時書き込みシナリオではパフォーマンスが低下します。テーブルが損傷しやすく、失敗から回復する能力がありません。
-
メモリ:
- 利点: データは完全にメモリに保存され、読み取りと書き込みは非常に高速です。キャッシュ テーブル、一時テーブル、高速データ キャプチャなどのシナリオに適しています。
- 短所: メモリにのみ保存できるため、停電や再起動によりデータが失われます。トランザクション処理はサポートされていないため、長期保存には適していません。
-
アーカイブ:
- 利点: アーカイブおよび履歴データの保存に適しており、保存効率と圧縮効率が非常に高く、必要なディスク容量が非常に少ないです。データがまばらに挿入され、更新頻度が低いシナリオに適しています。
- 欠点: インデックス作成とトランザクション処理はサポートされていません。実行できるのは追加操作のみであり、通常のクエリおよび更新操作には適していません。
-
NDB クラスター:
- 利点: 高可用性と大容量の分散システムに適しており、データのシャーディングと自動障害回復をサポートします。トランザクション処理と ACID 特性を備えており、同時読み取りと書き込みおよびリアルタイム アプリケーションのシナリオに適しています。
- 短所: 比較的複雑で、特別な構成と管理が必要で、高いハードウェア要件が必要です。スタンドアロンおよび小規模アプリケーションには適していません。
これらのストレージ エンジンの選択は、実際のニーズとアプリケーション シナリオに基づいて決定し、各ストレージ エンジンの長所と短所を比較検討し、特定のストレージ エンジンの読み取りおよび書き込み要件、データの一貫性、可用性の要件に基づいて最適なストレージ エンジンを決定する必要があります。シナリオ。
11. Docker C/S アーキテクチャ図を描いてください
Docker C/S アーキテクチャには、次の主要なコンポーネントがあります。
- Docker ホスト: Docker エンジンを実行する物理マシンまたは仮想マシンです。Docker ホストは、コンテナーの作成、実行、破棄、およびコンテナーのリソース管理と分離の管理を担当します。
- Docker エンジン: Docker のコア コンポーネントであり、Docker クライアントからのコマンドを受信して処理し、コンテナーの作成、実行、停止などの操作を実行します。Docker エンジンは、Docker デーモンと Docker REST API で構成されます。
- Docker クライアント: Docker エンジンと通信するユーザー インターフェイスです。コマンド ライン ツール (docker コマンドなど) またはグラフィカル インターフェイス ツールを使用して、Docker エンジンと対話し、Docker エンジンにコマンドを送信してコンテナーを制御できます。 、実行および管理します。
- Docker イメージ: これはコンテナーの基礎であり、コンテナーのテンプレートを作成するために使用されます。Docker イメージには、実行に必要なすべてのファイルと構成を含む完全なファイル システムが含まれています。独自のイメージを構築するには、Docker Hub またはプライベート イメージ リポジトリから既存のイメージをダウンロードするか、Dockerfile を使用します。
- Docker Registry: Docker イメージを保存および共有するための中央リポジトリです。Docker Hub はデフォルトのパブリック リポジトリで、ユーザーが使用できる公式およびコミュニティが管理するイメージを多数提供します。ユーザーは、プライベート Docker リポジトリをデプロイして、独自のイメージを保存および管理することもできます。
12. dockerコマンドを使用して操作してください
a) kuma という名前のボリュームを作成します。
docker volume create kuma
b) yapi という名前のコンテナを起動し、バックグラウンドで実行し、ホストの 5000 ポートをコンテナ内の 3000 ポートにマップし、上で作成したボリュームを使用して /data/db ディレクトリにマウントします。
docker run -d --name yapi -p 5000:3000 -v kuma:/data/db <yapi_image_name>
<yapi_image_name>
実際の yapi イメージ名に置き換える必要があります。
このようにして、上記の手順で作成したボリューム kuma を使用してコンテナ内の /data/db ディレクトリにマウントし、同時にポート マッピングを実行して、ホストの 5000 ポートをコンテナ内の 3000 ポートにマッピングすることができます。コンテナ。コンテナー名は yapi で、バックグラウンド モードで実行されます。
この記事の参考文献の一部は次のとおりです。
https://blog.csdn.net/baidu_36943075/article/details/107671011
https://www.cnblogs.com/jiangchunsheng/p/8986532.html
https://www.cnblogs.com/MrYuChen-Blog/p/15571639.html
https://www.cnblogs.com/sunsky303/p/8274586.html
https://blog.csdn.net/weixin_45455015/article/details/100113330